From d73496fd51e5eb98dcdc8006f4b516dc21d33656 Mon Sep 17 00:00:00 2001 From: Justin Wang <35274216+Claimundefine@users.noreply.github.com> Date: Tue, 20 Aug 2024 22:18:52 -0400 Subject: [PATCH] Add clientConfig, baseUrl retry, RestError, encodeURIComponent (#12) (#68) * Add clientConfig, baseUrl retry, RestError * refactor such that RestService takes in necessary dependencies --- dekregistry/dekregistry-client.ts | 28 ++- .../schemaregistry-client.spec.ts | 20 +- schemaregistry/rest-error.ts | 10 + schemaregistry/rest-service.ts | 64 +++--- schemaregistry/schemaregistry-client.ts | 144 +++++++------ test/dekregistry/dekregistry-client.spec.ts | 39 ++-- .../schemaregistry-client.spec.ts | 194 +++++++++--------- test/schemaregistry/test-constants.ts | 35 ++++ 8 files changed, 315 insertions(+), 219 deletions(-) create mode 100644 schemaregistry/rest-error.ts create mode 100644 test/schemaregistry/test-constants.ts diff --git a/dekregistry/dekregistry-client.ts b/dekregistry/dekregistry-client.ts index 886b62a9..ff59fa5a 100644 --- a/dekregistry/dekregistry-client.ts +++ b/dekregistry/dekregistry-client.ts @@ -1,8 +1,17 @@ import { LRUCache } from 'lru-cache'; import { Mutex } from 'async-mutex'; -import { RestService } from '../schemaregistry/rest-service'; +import { ClientConfig, RestService } from '../schemaregistry/rest-service'; import stringify from 'json-stringify-deterministic'; +/* + * Confluent-Schema-Registry-TypeScript - Node.js wrapper for Confluent Schema Registry + * + * Copyright (c) 2024 Confluent, Inc. + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE.txt file for details. + */ + interface Kek { name?: string; kmsType?: string; @@ -51,13 +60,14 @@ class DekRegistryClient implements Client { private kekMutex: Mutex; private dekMutex: Mutex; - constructor(restService: RestService, cacheSize: number = 512, cacheTTL?: number) { + constructor(config: ClientConfig) { const cacheOptions = { - max: cacheSize, - ...(cacheTTL !== undefined && { maxAge: cacheTTL }) + max: config.cacheCapacity, + ...(config.cacheLatestTtlSecs !== undefined && { maxAge: config.cacheLatestTtlSecs * 1000 }), }; - this.restService = restService; + + this.restService = new RestService(config.createAxiosDefaults, config.baseURLs, config.isForward); this.kekCache = new LRUCache(cacheOptions); this.dekCache = new LRUCache(cacheOptions); this.kekMutex = new Mutex(); @@ -124,7 +134,7 @@ class DekRegistryClient implements Client { shared, }; - const response = await this.restService.sendHttpRequest( + const response = await this.restService.handleRequest( '/dek-registry/v1/keks', 'POST', request); @@ -143,7 +153,7 @@ class DekRegistryClient implements Client { } name = encodeURIComponent(name); - const response = await this.restService.sendHttpRequest( + const response = await this.restService.handleRequest( `/dek-registry/v1/keks/${name}?deleted=${deleted}`, 'GET'); this.kekCache.set(cacheKey, response.data); @@ -169,7 +179,7 @@ class DekRegistryClient implements Client { }; kekName = encodeURIComponent(kekName); - const response = await this.restService.sendHttpRequest( + const response = await this.restService.handleRequest( `/dek-registry/v1/keks/${kekName}/deks`, 'POST', request); @@ -194,7 +204,7 @@ class DekRegistryClient implements Client { kekName = encodeURIComponent(kekName); subject = encodeURIComponent(subject); - const response = await this.restService.sendHttpRequest( + const response = await this.restService.handleRequest( `/dek-registry/v1/keks/${kekName}/deks/${subject}/versions/${version}?deleted=${deleted}`, 'GET'); this.dekCache.set(cacheKey, response.data); diff --git a/e2e/schemaregistry/schemaregistry-client.spec.ts b/e2e/schemaregistry/schemaregistry-client.spec.ts index 3854e2f2..2b0684fa 100644 --- a/e2e/schemaregistry/schemaregistry-client.spec.ts +++ b/e2e/schemaregistry/schemaregistry-client.spec.ts @@ -1,4 +1,3 @@ -import { RestService } from '../../schemaregistry/rest-service'; import { Compatibility, SchemaRegistryClient, @@ -8,19 +7,10 @@ import { Metadata } from '../../schemaregistry/schemaregistry-client'; import { beforeEach, describe, expect, it } from '@jest/globals'; +import { clientConfig } from '../../test/schemaregistry/test-constants'; /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ -const baseUrls = ['http://localhost:8081']; -const headers = { 'Content-Type': 'application/vnd.schemaregistry.v1+json' }; -const restService = new RestService(baseUrls, false); -restService.setHeaders(headers); - -const basicAuth = Buffer.from('RBACAllowedUser-lsrc1:nohash').toString('base64'); -restService.setAuth(basicAuth); - -restService.setTimeout(10000); - let schemaRegistryClient: SchemaRegistryClient; const testSubject = 'integ-test-subject'; const testServerConfigSubject = 'integ-test-server-config-subject'; @@ -72,7 +62,7 @@ const backwardCompatibleSchemaInfo: SchemaInfo = { describe('SchemaRegistryClient Integration Test', () => { beforeEach(async () => { - schemaRegistryClient = new SchemaRegistryClient(restService); + schemaRegistryClient = new SchemaRegistryClient(clientConfig); const subjects: string[] = await schemaRegistryClient.getAllSubjects(); if (subjects && subjects.includes(testSubject)) { @@ -86,7 +76,11 @@ describe('SchemaRegistryClient Integration Test', () => { } }); - it('should register, retrieve, and delete a schema', async () => { + it("Should return RestError when retrieving non-existent schema", async () => { + await expect(schemaRegistryClient.getBySubjectAndId(testSubject, 1)).rejects.toThrow(); + }); + + it('Should register, retrieve, and delete a schema', async () => { // Register a schema const registerResponse: SchemaMetadata = await schemaRegistryClient.registerFullResponse(testSubject, schemaInfo); expect(registerResponse).toBeDefined(); diff --git a/schemaregistry/rest-error.ts b/schemaregistry/rest-error.ts new file mode 100644 index 00000000..19fd086a --- /dev/null +++ b/schemaregistry/rest-error.ts @@ -0,0 +1,10 @@ +export class RestError extends Error { + status: number; + errorCode: number; + + constructor(message: string, status: number, errorCode: number) { + super(message + "; Error code: " + errorCode); + this.status = status; + this.errorCode = errorCode; + } +} \ No newline at end of file diff --git a/schemaregistry/rest-service.ts b/schemaregistry/rest-service.ts index e93d7746..333fc46a 100644 --- a/schemaregistry/rest-service.ts +++ b/schemaregistry/rest-service.ts @@ -1,4 +1,5 @@ -import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; +import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, CreateAxiosDefaults } from 'axios'; +import { RestError } from './rest-error'; /* * Confluent-Schema-Registry-TypeScript - Node.js wrapper for Confluent Schema Registry @@ -9,43 +10,60 @@ import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; * of the MIT license. See the LICENSE.txt file for details. */ +export type ClientConfig = { + createAxiosDefaults: CreateAxiosDefaults, + baseURLs: string[], + cacheCapacity: number, + cacheLatestTtlSecs?: number, + isForward?: boolean +} + export class RestService { - private client: AxiosInstance + private client: AxiosInstance; + private baseURLs: string[]; - constructor(baseUrls: string[], isForward = false) { - this.client = axios.create({ - baseURL: baseUrls[0], // Use the first base URL as the default - timeout: 5000, // Default timeout - headers: { 'Content-Type': 'application/vnd.schemaregistry.v1+json' }, - }) + constructor(axiosDefaults: CreateAxiosDefaults, baseURLs: string[], isForward?: boolean) { + this.client = axios.create(axiosDefaults); + this.baseURLs = baseURLs; if (isForward) { this.client.defaults.headers.common['X-Forward'] = 'true' } } - public async sendHttpRequest( + public async handleRequest( url: string, method: 'GET' | 'POST' | 'PUT' | 'DELETE', data?: any, // eslint-disable-line @typescript-eslint/no-explicit-any config?: AxiosRequestConfig, ): Promise> { - try { - const response = await this.client.request({ - url, - method, - data, - ...config, - }) - return response - } catch (error) { - if (axios.isAxiosError(error) && error.response) { - throw new Error(`HTTP error: ${error.response.status} - ${error.response.data}`) - } else { - const err = error as Error; - throw new Error(`Unknown error: ${err.message}`) + + for (let i = 0; i < this.baseURLs.length; i++) { + try { + this.setBaseURL(this.baseURLs[i]); + const response = await this.client.request({ + url, + method, + data, + ...config, + }) + return response; + } catch (error) { + if (axios.isAxiosError(error) && error.response && (error.response.status < 200 || error.response.status > 299)) { + const data = error.response.data; + if (data.error_code && data.message) { + error = new RestError(data.message, error.response.status, data.error_code); + } else { + error = new Error(`Unknown error: ${error.message}`) + } + } + if (i === this.baseURLs.length - 1) { + throw error; + } } } + + throw new Error('Internal HTTP retry error'); // Should never reach here } public setHeaders(headers: Record): void { diff --git a/schemaregistry/schemaregistry-client.ts b/schemaregistry/schemaregistry-client.ts index 4bd62459..bb0a25e3 100644 --- a/schemaregistry/schemaregistry-client.ts +++ b/schemaregistry/schemaregistry-client.ts @@ -1,4 +1,4 @@ -import { RestService } from './rest-service'; +import { RestService, ClientConfig } from './rest-service'; import { AxiosResponse } from 'axios'; import stringify from "json-stringify-deterministic"; import { LRUCache } from 'lru-cache'; @@ -28,11 +28,6 @@ interface CompatibilityLevel { compatibilityLevel?: Compatibility; } -interface Result { - data?: T; - error?: Error; -} - interface Rule { name: string; subject: string; @@ -131,13 +126,14 @@ class SchemaRegistryClient implements Client { private versionToSchemaMutex: Mutex; private metadataToSchemaMutex: Mutex; - constructor(restService: RestService, cacheSize: number = 512, cacheTTL?: number) { + constructor(config: ClientConfig) { const cacheOptions = { - max: cacheSize, - ...(cacheTTL !== undefined && { maxAge: cacheTTL }) + max: config.cacheCapacity, + ...(config.cacheLatestTtlSecs !== undefined && { maxAge: config.cacheLatestTtlSecs * 1000 }) }; - this.restService = restService; + this.restService = new RestService(config.createAxiosDefaults, config.baseURLs, config.isForward); + this.schemaToIdCache = new LRUCache(cacheOptions); this.idToSchemaInfoCache = new LRUCache(cacheOptions); this.infoToSchemaCache = new LRUCache(cacheOptions); @@ -169,7 +165,9 @@ class SchemaRegistryClient implements Client { return cachedSchemaMetadata; } - const response: AxiosResponse = await this.restService.sendHttpRequest( + subject = encodeURIComponent(subject); + + const response: AxiosResponse = await this.restService.handleRequest( `/subjects/${subject}/versions?normalize=${normalize}`, 'POST', schema @@ -187,7 +185,9 @@ class SchemaRegistryClient implements Client { return cachedSchema; } - const response: AxiosResponse = await this.restService.sendHttpRequest( + subject = encodeURIComponent(subject); + + const response: AxiosResponse = await this.restService.handleRequest( `/schemas/ids/${id}?subject=${subject}`, 'GET' ); @@ -205,7 +205,9 @@ class SchemaRegistryClient implements Client { return cachedId; } - const response: AxiosResponse = await this.restService.sendHttpRequest( + subject = encodeURIComponent(subject); + + const response: AxiosResponse = await this.restService.handleRequest( `/subjects/${subject}?normalize=${normalize}`, 'POST', schema @@ -222,7 +224,9 @@ class SchemaRegistryClient implements Client { return cachedSchema; } - const response: AxiosResponse = await this.restService.sendHttpRequest( + subject = encodeURIComponent(subject); + + const response: AxiosResponse = await this.restService.handleRequest( `/subjects/${subject}/versions/latest`, 'GET' ); @@ -240,7 +244,9 @@ class SchemaRegistryClient implements Client { return cachedSchemaMetadata; } - const response: AxiosResponse = await this.restService.sendHttpRequest( + subject = encodeURIComponent(subject); + + const response: AxiosResponse = await this.restService.handleRequest( `/subjects/${subject}/versions/${version}?deleted=${deleted}`, 'GET' ); @@ -251,13 +257,15 @@ class SchemaRegistryClient implements Client { public async getLatestWithMetadata(subject: string, metadata: { [key: string]: string }, deleted: boolean = false): Promise { const cacheKey = stringify({ subject, metadata, deleted }); - + return await this.metadataToSchemaMutex.runExclusive(async () => { const cachedSchemaMetadata: SchemaMetadata | undefined = this.metadataToSchemaCache.get(cacheKey); if (cachedSchemaMetadata) { return cachedSchemaMetadata; } + subject = encodeURIComponent(subject); + let metadataStr = ''; for (const key in metadata) { @@ -266,7 +274,7 @@ class SchemaRegistryClient implements Client { metadataStr += `&key=${encodedKey}&value=${encodedValue}`; } - const response: AxiosResponse = await this.restService.sendHttpRequest( + const response: AxiosResponse = await this.restService.handleRequest( `/subjects/${subject}/metadata?deleted=${deleted}&${metadataStr}`, 'GET' ); @@ -277,7 +285,7 @@ class SchemaRegistryClient implements Client { public async getAllVersions(subject: string): Promise { - const response: AxiosResponse = await this.restService.sendHttpRequest( + const response: AxiosResponse = await this.restService.handleRequest( `/subjects/${subject}/versions`, 'GET' ); @@ -293,7 +301,9 @@ class SchemaRegistryClient implements Client { return cachedVersion; } - const response: AxiosResponse = await this.restService.sendHttpRequest( + subject = encodeURIComponent(subject); + + const response: AxiosResponse = await this.restService.handleRequest( `/subjects/${subject}?normalize=${normalize}`, 'POST', schema @@ -304,7 +314,7 @@ class SchemaRegistryClient implements Client { } public async getAllSubjects(): Promise { - const response: AxiosResponse = await this.restService.sendHttpRequest( + const response: AxiosResponse = await this.restService.handleRequest( `/subjects`, 'GET' ); @@ -348,7 +358,9 @@ class SchemaRegistryClient implements Client { }); }); - const response: AxiosResponse = await this.restService.sendHttpRequest( + subject = encodeURIComponent(subject); + + const response: AxiosResponse = await this.restService.handleRequest( `/subjects/${subject}?permanent=${permanent}`, 'DELETE' ); @@ -384,7 +396,9 @@ class SchemaRegistryClient implements Client { this.versionToSchemaCache.delete(cacheKey); }); - const response: AxiosResponse = await this.restService.sendHttpRequest( + subject = encodeURIComponent(subject); + + const response: AxiosResponse = await this.restService.handleRequest( `/subjects/${subject}/versions/${version}?permanent=${permanent}`, 'DELETE' ); @@ -393,7 +407,9 @@ class SchemaRegistryClient implements Client { } public async testSubjectCompatibility(subject: string, schema: SchemaInfo): Promise { - const response: AxiosResponse = await this.restService.sendHttpRequest( + subject = encodeURIComponent(subject); + + const response: AxiosResponse = await this.restService.handleRequest( `/compatibility/subjects/${subject}/versions/latest`, 'POST', schema @@ -402,7 +418,9 @@ class SchemaRegistryClient implements Client { } public async testCompatibility(subject: string, version: number, schema: SchemaInfo): Promise { - const response: AxiosResponse = await this.restService.sendHttpRequest( + subject = encodeURIComponent(subject); + + const response: AxiosResponse = await this.restService.handleRequest( `/compatibility/subjects/${subject}/versions/${version}`, 'POST', schema @@ -411,7 +429,9 @@ class SchemaRegistryClient implements Client { } public async getCompatibility(subject: string): Promise { - const response: AxiosResponse = await this.restService.sendHttpRequest( + subject = encodeURIComponent(subject); + + const response: AxiosResponse = await this.restService.handleRequest( `/config/${subject}`, 'GET' ); @@ -419,7 +439,9 @@ class SchemaRegistryClient implements Client { } public async updateCompatibility(subject: string, update: Compatibility): Promise { - const response: AxiosResponse = await this.restService.sendHttpRequest( + subject = encodeURIComponent(subject); + + const response: AxiosResponse = await this.restService.handleRequest( `/config/${subject}`, 'PUT', { compatibility: update } @@ -428,54 +450,56 @@ class SchemaRegistryClient implements Client { } public async getDefaultCompatibility(): Promise { - const response: AxiosResponse = await this.restService.sendHttpRequest( - `/config`, - 'GET' - ); - return response.data.compatibilityLevel!; + const response: AxiosResponse = await this.restService.handleRequest( + `/config`, + 'GET' + ); + return response.data.compatibilityLevel!; } public async updateDefaultCompatibility(update: Compatibility): Promise { - const response: AxiosResponse = await this.restService.sendHttpRequest( - `/config`, - 'PUT', - { compatibility: update } - ); - return response.data.compatibility!; + const response: AxiosResponse = await this.restService.handleRequest( + `/config`, + 'PUT', + { compatibility: update } + ); + return response.data.compatibility!; } public async getConfig(subject: string): Promise { - const response: AxiosResponse = await this.restService.sendHttpRequest( - `/config/${subject}`, - 'GET' - ); - return response.data; + subject = encodeURIComponent(subject); + + const response: AxiosResponse = await this.restService.handleRequest( + `/config/${subject}`, + 'GET' + ); + return response.data; } public async updateConfig(subject: string, update: ServerConfig): Promise { - const response: AxiosResponse = await this.restService.sendHttpRequest( - `/config/${subject}`, - 'PUT', - update - ); - return response.data; + const response: AxiosResponse = await this.restService.handleRequest( + `/config/${subject}`, + 'PUT', + update + ); + return response.data; } public async getDefaultConfig(): Promise { - const response: AxiosResponse = await this.restService.sendHttpRequest( - `/config`, - 'GET' - ); - return response.data; + const response: AxiosResponse = await this.restService.handleRequest( + `/config`, + 'GET' + ); + return response.data; } public async updateDefaultConfig(update: ServerConfig): Promise { - const response: AxiosResponse = await this.restService.sendHttpRequest( - `/config`, - 'PUT', - update - ); - return response.data; + const response: AxiosResponse = await this.restService.handleRequest( + `/config`, + 'PUT', + update + ); + return response.data; } public close(): void { @@ -544,5 +568,5 @@ class SchemaRegistryClient implements Client { export { Client, SchemaRegistryClient, SchemaInfo, Metadata, Compatibility, - CompatibilityLevel, ServerConfig, RuleSet, Rule, Reference, SchemaMetadata, Result + CompatibilityLevel, ServerConfig, RuleSet, Rule, Reference, SchemaMetadata }; diff --git a/test/dekregistry/dekregistry-client.spec.ts b/test/dekregistry/dekregistry-client.spec.ts index bd0823b7..f6de5fcd 100644 --- a/test/dekregistry/dekregistry-client.spec.ts +++ b/test/dekregistry/dekregistry-client.spec.ts @@ -6,10 +6,10 @@ import { TEST_KEK, TEST_KEK_2, TEST_KEK_NAME, TEST_KEK_NAME_2, TEST_KMS_TYPE, TE TEST_KMS_PROPS, TEST_DOC, TEST_DEK, TEST_DEK_2, TEST_ALGORITHM, TEST_ENCRYPTED_KEY_MATERIAL, TEST_SUBJECT, TEST_VERSION, TEST_DEK_LATEST} from "./test-constants"; +import { mockClientConfig } from "../schemaregistry/test-constants"; jest.mock('../../schemaregistry/rest-service'); -const baseUrls = ['http://mocked-url']; let client: DekRegistryClient; let restService: jest.Mocked; @@ -17,8 +17,9 @@ let restService: jest.Mocked; describe('DekRegistryClient', () => { beforeEach(() => { - restService = new RestService(baseUrls) as jest.Mocked; - client = new DekRegistryClient(restService); + restService = new RestService(mockClientConfig.createAxiosDefaults, mockClientConfig.baseURLs) as jest.Mocked; + client = new DekRegistryClient(mockClientConfig); + (client as any).restService = restService; }); afterEach(() => { @@ -26,18 +27,18 @@ describe('DekRegistryClient', () => { }); it('Should register kek when registerKek is called', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: TEST_KEK } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: TEST_KEK } as AxiosResponse); const response: Kek = await client.registerKek( TEST_KEK_NAME, TEST_KMS_TYPE, TEST_KMS_KEY_ID, TEST_KMS_PROPS, TEST_DOC, true); expect(response).toEqual(TEST_KEK); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should return kek from cache when registerKek is called with same kek name', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: TEST_KEK } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: TEST_KEK } as AxiosResponse); await client.registerKek(TEST_KEK_NAME, TEST_KMS_TYPE, TEST_KMS_KEY_ID, TEST_KMS_PROPS, TEST_DOC, true); - restService.sendHttpRequest.mockResolvedValue({ data: TEST_KEK_2 } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: TEST_KEK_2 } as AxiosResponse); await client.registerKek(TEST_KEK_NAME_2, TEST_KMS_TYPE, TEST_KMS_KEY_ID, TEST_KMS_PROPS, TEST_DOC, true); const response: Kek = await client.registerKek( @@ -47,29 +48,29 @@ describe('DekRegistryClient', () => { expect(response).toEqual(TEST_KEK); expect(response2).toEqual(TEST_KEK_2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); }); it('Should return kek from cache when getKek is called with same kek name', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: TEST_KEK } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: TEST_KEK } as AxiosResponse); await client.registerKek(TEST_KEK_NAME, TEST_KMS_TYPE, TEST_KMS_KEY_ID, TEST_KMS_PROPS, TEST_DOC, true); const response: Kek = await client.getKek(TEST_KEK_NAME); expect(response).toEqual(TEST_KEK); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should register dek when registerDek is called', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: TEST_DEK } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: TEST_DEK } as AxiosResponse); const response: Dek = await client.registerDek(TEST_KEK_NAME, TEST_SUBJECT, TEST_ALGORITHM, TEST_ENCRYPTED_KEY_MATERIAL, TEST_VERSION); expect(response).toEqual(TEST_DEK); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should return dek from cache when registerDek is called with same kek name, subject, algorithm, and version', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: TEST_DEK } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: TEST_DEK } as AxiosResponse); await client.registerDek(TEST_KEK_NAME, TEST_SUBJECT, TEST_ALGORITHM, TEST_ENCRYPTED_KEY_MATERIAL, TEST_VERSION); - restService.sendHttpRequest.mockResolvedValue({ data: TEST_DEK_2 } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: TEST_DEK_2 } as AxiosResponse); await client.registerDek(TEST_KEK_NAME_2, TEST_SUBJECT, TEST_ALGORITHM, TEST_ENCRYPTED_KEY_MATERIAL, TEST_VERSION); const response: Dek = await client.registerDek(TEST_KEK_NAME, TEST_SUBJECT, TEST_ALGORITHM, TEST_ENCRYPTED_KEY_MATERIAL, TEST_VERSION); @@ -77,25 +78,25 @@ describe('DekRegistryClient', () => { expect(response).toEqual(TEST_DEK); expect(response2).toEqual(TEST_DEK_2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); }); it('Should return dek from cache when getDek is called with same kek name, subject, algorithm, and version', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: TEST_DEK } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: TEST_DEK } as AxiosResponse); await client.registerDek(TEST_KEK_NAME, TEST_SUBJECT, TEST_ALGORITHM, TEST_ENCRYPTED_KEY_MATERIAL, TEST_VERSION); const response: Dek = await client.getDek(TEST_KEK_NAME, TEST_SUBJECT, TEST_ALGORITHM, TEST_VERSION); expect(response).toEqual(TEST_DEK); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should delete dek with version -1 when registerDek is called', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: TEST_DEK_LATEST } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: TEST_DEK_LATEST } as AxiosResponse); const getDekResponse: Dek = await client.getDek(TEST_KEK_NAME, TEST_SUBJECT, TEST_ALGORITHM, -1); expect(getDekResponse).toEqual(TEST_DEK_LATEST); expect(await client.checkLatestDekInCache(TEST_KEK_NAME, TEST_SUBJECT, TEST_ALGORITHM)).toBe(true); - restService.sendHttpRequest.mockResolvedValue({ data: TEST_DEK } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: TEST_DEK } as AxiosResponse); await client.registerDek(TEST_KEK_NAME, TEST_SUBJECT, TEST_ALGORITHM, TEST_ENCRYPTED_KEY_MATERIAL, TEST_VERSION); const getDekResponse2: Dek = await client.getDek(TEST_KEK_NAME, TEST_SUBJECT, TEST_ALGORITHM); diff --git a/test/schemaregistry/schemaregistry-client.spec.ts b/test/schemaregistry/schemaregistry-client.spec.ts index a146a2de..6c43ba6e 100644 --- a/test/schemaregistry/schemaregistry-client.spec.ts +++ b/test/schemaregistry/schemaregistry-client.spec.ts @@ -10,11 +10,10 @@ import { RestService } from '../../schemaregistry/rest-service'; import { AxiosResponse } from 'axios'; import stringify from "json-stringify-deterministic"; import { beforeEach, afterEach, describe, expect, it, jest } from '@jest/globals'; +import { mockClientConfig } from '../../test/schemaregistry/test-constants'; jest.mock('../../schemaregistry/rest-service'); -const baseUrls = ['http://mocked-url']; - let client: SchemaRegistryClient; let restService: jest.Mocked; const mockSubject = 'mock-subject'; @@ -80,8 +79,9 @@ const versions: number[] = [1, 2, 3]; describe('SchemaRegistryClient-Register', () => { beforeEach(() => { - restService = new RestService(baseUrls) as jest.Mocked; - client = new SchemaRegistryClient(restService); + restService = new RestService(mockClientConfig.createAxiosDefaults, mockClientConfig.baseURLs) as jest.Mocked; + client = new SchemaRegistryClient(mockClientConfig); + (client as any).restService = restService; }); afterEach(() => { @@ -89,37 +89,37 @@ describe('SchemaRegistryClient-Register', () => { }); it('Should return id when Register is called', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: { id: 1 } } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: { id: 1 } } as AxiosResponse); const response: number = await client.register(mockSubject, schemaInfo); expect(response).toEqual(1); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should return from cache when Register is called twice', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: { id: 1 } } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: { id: 1 } } as AxiosResponse); const response: number = await client.register(mockSubject, schemaInfo); expect(response).toEqual(1); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); - restService.sendHttpRequest.mockResolvedValue({ data: { id: 2 } } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: { id: 2 } } as AxiosResponse); const response2: number = await client.register(mockSubject2, schemaInfo2); expect(response2).toEqual(2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); //Try to create same objects again const cachedResponse: number = await client.register(mockSubject, schemaInfo); expect(cachedResponse).toEqual(1); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); const cachedResponse2: number = await client.register(mockSubject2, schemaInfo2); expect(cachedResponse2).toEqual(2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); }); it('Should return id, version, metadata, and schema when RegisterFullResponse is called', async () => { @@ -130,12 +130,12 @@ describe('SchemaRegistryClient-Register', () => { metadata: metadata, }; - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); const response: SchemaMetadata = await client.registerFullResponse(mockSubject, schemaInfoMetadata); expect(response).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should return id, version, metadata, and schema from cache when RegisterFullResponse is called twice', async () => { @@ -152,66 +152,67 @@ describe('SchemaRegistryClient-Register', () => { metadata: metadata2, }; - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); const response: SchemaMetadata = await client.registerFullResponse(mockSubject, schemaInfoMetadata); expect(response).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse2 } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse2 } as AxiosResponse); const response2: SchemaMetadata = await client.registerFullResponse(mockSubject2, schemaInfoMetadata2); expect(response2).toMatchObject(expectedResponse2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); const cachedResponse: SchemaMetadata = await client.registerFullResponse(mockSubject, schemaInfoMetadata); expect(cachedResponse).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); const cachedResponse2: SchemaMetadata = await client.registerFullResponse(mockSubject2, schemaInfoMetadata2); expect(cachedResponse2).toMatchObject(expectedResponse2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); }); }); describe('SchemaRegistryClient-Get-ID', () => { beforeEach(() => { - restService = new RestService(baseUrls) as jest.Mocked; - client = new SchemaRegistryClient(restService); + restService = new RestService(mockClientConfig.createAxiosDefaults, mockClientConfig.baseURLs) as jest.Mocked; + client = new SchemaRegistryClient(mockClientConfig); + (client as any).restService = restService; }); afterEach(() => { jest.clearAllMocks(); }); it('Should return id when GetId is called', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: { id: 1 } } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: { id: 1 } } as AxiosResponse); const response: number = await client.getId(mockSubject, schemaInfo); expect(response).toEqual(1); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should return id from cache when GetId is called twice', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: { id: 1 } } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: { id: 1 } } as AxiosResponse); const response: number = await client.getId(mockSubject, schemaInfo); expect(response).toEqual(1); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); - restService.sendHttpRequest.mockResolvedValue({ data: { id: 2 } } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: { id: 2 } } as AxiosResponse); const response2: number = await client.getId(mockSubject2, schemaInfo2); expect(response2).toEqual(2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); const cachedResponse: number = await client.getId(mockSubject, schemaInfo); expect(cachedResponse).toEqual(1); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); const cachedResponse2: number = await client.getId(mockSubject2, schemaInfo2); expect(cachedResponse2).toEqual(2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); }); it('Should return SchemaInfo when GetBySubjectAndId is called', async () => { @@ -222,12 +223,12 @@ describe('SchemaRegistryClient-Get-ID', () => { metadata: metadata, }; - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); const response: SchemaInfo = await client.getBySubjectAndId(mockSubject, 1); expect(response).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should return SchemaInfo from cache when GetBySubjectAndId is called twice', async () => { @@ -244,32 +245,33 @@ describe('SchemaRegistryClient-Get-ID', () => { metadata: metadata2, }; - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); const response: SchemaInfo = await client.getBySubjectAndId(mockSubject, 1); expect(response).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse2 } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse2 } as AxiosResponse); const response2: SchemaInfo = await client.getBySubjectAndId(mockSubject2, 2); expect(response2).toMatchObject(expectedResponse2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); const cachedResponse: SchemaInfo = await client.getBySubjectAndId(mockSubject, 1); expect(cachedResponse).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); const cachedResponse2: SchemaInfo = await client.getBySubjectAndId(mockSubject2, 2); expect(cachedResponse2).toMatchObject(expectedResponse2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); }); }); describe('SchemaRegistryClient-Get-Schema-Metadata', () => { beforeEach(() => { - restService = new RestService(baseUrls) as jest.Mocked; - client = new SchemaRegistryClient(restService); + restService = new RestService(mockClientConfig.createAxiosDefaults, mockClientConfig.baseURLs) as jest.Mocked; + client = new SchemaRegistryClient(mockClientConfig); + (client as any).restService = restService; }); afterEach(() => { jest.clearAllMocks(); @@ -283,12 +285,12 @@ describe('SchemaRegistryClient-Get-Schema-Metadata', () => { metadata: metadata, }; - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); const response: SchemaMetadata = await client.getLatestWithMetadata(mockSubject, metadataKeyValue); expect(response).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should return latest schema with metadata from cache when GetLatestWithMetadata is called twice', async () => { @@ -305,25 +307,25 @@ describe('SchemaRegistryClient-Get-Schema-Metadata', () => { metadata: metadata2, }; - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); const response: SchemaMetadata = await client.getLatestWithMetadata(mockSubject, metadataKeyValue); expect(response).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse2 } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse2 } as AxiosResponse); const response2: SchemaMetadata = await client.getLatestWithMetadata(mockSubject2, metadataKeyValue2); expect(response2).toMatchObject(expectedResponse2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); const cachedResponse: SchemaMetadata = await client.getLatestWithMetadata(mockSubject, metadataKeyValue); expect(cachedResponse).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); const cachedResponse2: SchemaMetadata = await client.getLatestWithMetadata(mockSubject2, metadataKeyValue2); expect(cachedResponse2).toMatchObject(expectedResponse2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); }); it('Should return SchemaMetadata when GetSchemaMetadata is called', async () => { @@ -334,12 +336,12 @@ describe('SchemaRegistryClient-Get-Schema-Metadata', () => { metadata: metadata, }; - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); const response: SchemaMetadata = await client.getSchemaMetadata(mockSubject, 1, true); expect(response).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should return SchemaMetadata from cache when GetSchemaMetadata is called twice', async () => { @@ -356,53 +358,54 @@ describe('SchemaRegistryClient-Get-Schema-Metadata', () => { metadata: metadata2, }; - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); const response: SchemaMetadata = await client.getSchemaMetadata(mockSubject, 1, true); expect(response).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse2 } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse2 } as AxiosResponse); const response2: SchemaMetadata = await client.getSchemaMetadata(mockSubject2, 2, false); expect(response2).toMatchObject(expectedResponse2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); const cachedResponse: SchemaMetadata = await client.getSchemaMetadata(mockSubject, 1, true); expect(cachedResponse).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); const cachedResponse2: SchemaMetadata = await client.getSchemaMetadata(mockSubject2, 2, false); expect(cachedResponse2).toMatchObject(expectedResponse2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); }); }); describe('SchemaRegistryClient-Subjects', () => { beforeEach(() => { - restService = new RestService(baseUrls) as jest.Mocked; - client = new SchemaRegistryClient(restService); + restService = new RestService(mockClientConfig.createAxiosDefaults, mockClientConfig.baseURLs) as jest.Mocked; + client = new SchemaRegistryClient(mockClientConfig); + (client as any).restService = restService; }); afterEach(() => { jest.clearAllMocks(); }); it('Should return all subjects when GetAllSubjects is called', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: subjects } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: subjects } as AxiosResponse); const response: string[] = await client.getAllSubjects(); expect(response).toEqual(subjects); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should return all versions when GetAllVersions is called', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: versions } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: versions } as AxiosResponse); const response: number[] = await client.getAllVersions(mockSubject); expect(response).toEqual(versions); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should return version when GetVersion is called', async () => { @@ -410,12 +413,12 @@ describe('SchemaRegistryClient-Subjects', () => { schema: schemaString, schemaType: 'AVRO', }; - restService.sendHttpRequest.mockResolvedValue({ data: { version: 1 } } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: { version: 1 } } as AxiosResponse); const response: number = await client.getVersion(mockSubject, schemaInfo, true); expect(response).toEqual(1); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should return version from cache when GetVersion is called twice', async () => { @@ -428,25 +431,25 @@ describe('SchemaRegistryClient-Subjects', () => { schemaType: 'AVRO', }; - restService.sendHttpRequest.mockResolvedValue({ data: { version: 1 } } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: { version: 1 } } as AxiosResponse); const response: number = await client.getVersion(mockSubject, schemaInfo, true); expect(response).toEqual(1); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); - restService.sendHttpRequest.mockResolvedValue({ data: { version: 2 } } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: { version: 2 } } as AxiosResponse); const response2: number = await client.getVersion(mockSubject2, schemaInfo2, false); expect(response2).toEqual(2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); const cachedResponse: number = await client.getVersion(mockSubject, schemaInfo, true); expect(cachedResponse).toEqual(1); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); const cachedResponse2: number = await client.getVersion(mockSubject2, schemaInfo2, false); expect(cachedResponse2).toEqual(2); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(2); + expect(restService.handleRequest).toHaveBeenCalledTimes(2); }); it('Should delete subject from all caches and registry when deleteSubject is called', async () => { @@ -461,7 +464,7 @@ describe('SchemaRegistryClient-Subjects', () => { await client.addToVersionToSchemaCache(mockSubject, 1, expectedResponse); await client.addToIdToSchemaInfoCache(mockSubject, 1, schemaInfo); - restService.sendHttpRequest.mockResolvedValue({ data: [1] } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: [1] } as AxiosResponse); const response: number[] = await client.deleteSubject(mockSubject); @@ -471,7 +474,7 @@ describe('SchemaRegistryClient-Subjects', () => { expect(await client.getIdToSchemaInfoCacheSize()).toEqual(0); expect(response).toEqual([1]); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should delete subject version from all caches and registry when deleteSubjectVersion is called', async () => { @@ -486,7 +489,7 @@ describe('SchemaRegistryClient-Subjects', () => { await client.addToVersionToSchemaCache(mockSubject, 1, expectedResponse); await client.addToIdToSchemaInfoCache(mockSubject, 1, schemaInfo); - restService.sendHttpRequest.mockResolvedValue({ data: [1] } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: [1] } as AxiosResponse); const response: number = await client.deleteSubjectVersion(mockSubject, 1); @@ -496,61 +499,62 @@ describe('SchemaRegistryClient-Subjects', () => { expect(await client.getIdToSchemaInfoCacheSize()).toEqual(0); expect(response).toEqual([1]); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); }); describe('SchemaRegistryClient-Compatibility', () => { - beforeEach(() => { - restService = new RestService(baseUrls) as jest.Mocked; - client = new SchemaRegistryClient(restService); + restService = new RestService(mockClientConfig.createAxiosDefaults, mockClientConfig.baseURLs) as jest.Mocked; + client = new SchemaRegistryClient(mockClientConfig); + (client as any).restService = restService; }); afterEach(() => { jest.clearAllMocks(); }); it('Should return compatibility level when GetCompatibility is called', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: { compatibilityLevel: "BACKWARD" } } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: { compatibilityLevel: "BACKWARD" } } as AxiosResponse); const response: Compatibility = await client.getCompatibility(mockSubject); expect(response).toEqual('BACKWARD'); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should update compatibility level when updateCompatibility is called', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: { compatibility: 'BACKWARD' } } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: { compatibility: 'BACKWARD' } } as AxiosResponse); const response: Compatibility = await client.updateCompatibility(mockSubject, Compatibility.Backward); expect(response).toEqual(Compatibility.Backward); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should return Compatibility when getDefaultCompatibility is called', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: { compatibilityLevel: 'BACKWARD' } } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: { compatibilityLevel: 'BACKWARD' } } as AxiosResponse); const response: Compatibility = await client.getDefaultCompatibility(); expect(response).toEqual(Compatibility.Backward); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should update default compatibility level when updateDefaultCompatibility is called', async () => { - restService.sendHttpRequest.mockResolvedValue({ data: { compatibility: 'BACKWARD' } } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: { compatibility: 'BACKWARD' } } as AxiosResponse); const response: Compatibility = await client.updateDefaultCompatibility(Compatibility.Backward); expect(response).toEqual(Compatibility.Backward); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); }); describe('SchemaRegistryClient-Config', () => { beforeEach(() => { - restService = new RestService(baseUrls) as jest.Mocked; - client = new SchemaRegistryClient(restService); + restService = new RestService(mockClientConfig.createAxiosDefaults, mockClientConfig.baseURLs) as jest.Mocked; + client = new SchemaRegistryClient(mockClientConfig); + (client as any).restService = restService; }); afterEach(() => { jest.clearAllMocks(); @@ -563,12 +567,12 @@ describe('SchemaRegistryClient-Config', () => { normalize: true, }; - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); const response: ServerConfig = await client.getConfig(mockSubject); expect(response).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should update config when updateConfig is called', async () => { @@ -583,12 +587,12 @@ describe('SchemaRegistryClient-Config', () => { normalize: true, }; - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); const response: ServerConfig = await client.updateConfig(mockSubject, request); expect(response).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should return config when getDefaultConfig is called', async () => { @@ -598,12 +602,12 @@ describe('SchemaRegistryClient-Config', () => { normalize: true, }; - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); const response: ServerConfig = await client.getDefaultConfig(); expect(response).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); it('Should update default config when updateDefaultConfig is called', async () => { @@ -618,11 +622,11 @@ describe('SchemaRegistryClient-Config', () => { normalize: true, }; - restService.sendHttpRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); + restService.handleRequest.mockResolvedValue({ data: expectedResponse } as AxiosResponse); const response: ServerConfig = await client.updateDefaultConfig(request); expect(response).toMatchObject(expectedResponse); - expect(restService.sendHttpRequest).toHaveBeenCalledTimes(1); + expect(restService.handleRequest).toHaveBeenCalledTimes(1); }); }); \ No newline at end of file diff --git a/test/schemaregistry/test-constants.ts b/test/schemaregistry/test-constants.ts new file mode 100644 index 00000000..7a478765 --- /dev/null +++ b/test/schemaregistry/test-constants.ts @@ -0,0 +1,35 @@ +import { CreateAxiosDefaults } from 'axios'; +import { ClientConfig } from '../../schemaregistry/rest-service'; + +const baseUrls = ['http://localhost:8081']; + +const mockBaseUrls = ['http://mocked-url']; + +const createAxiosDefaults: CreateAxiosDefaults = { + headers: { + 'Content-Type': 'application/vnd.schemaregistry.v1+json', + }, + auth: { + username: 'RBACAllowedUser-lsrc1', + password: 'nohash', + }, + timeout: 10000 +}; + +const clientConfig: ClientConfig = { + baseURLs: baseUrls, + createAxiosDefaults: createAxiosDefaults, + isForward: false, + cacheCapacity: 512, + cacheLatestTtlSecs: 60, +}; + +const mockClientConfig: ClientConfig = { + baseURLs: mockBaseUrls, + createAxiosDefaults: createAxiosDefaults, + isForward: false, + cacheCapacity: 512, + cacheLatestTtlSecs: 60, +}; + +export { clientConfig, mockClientConfig };