UNPKG

@elastic.io/maester-client

Version:
335 lines (328 loc) 13.9 kB
/* eslint-disable max-len */ import 'mocha'; import chai, { expect } from 'chai'; import sinon from 'sinon'; import getStream from 'get-stream'; import chaiAsPromised from 'chai-as-promised'; import { getContext, streamFromObject } from './helpers'; import { ObjectStorageWrapper, StorageClient, MAESTER_MAX_SUPPORTED_COUNT_OF_QUERY_HEADERS } from '../src'; chai.use(chaiAsPromised); process.env.ELASTICIO_OBJECT_STORAGE_TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6I'; process.env.ELASTICIO_OBJECT_STORAGE_URI = 'https://ma.estr'; describe('ObjectStorageWrapper', () => { const objectStorageWrapper = new ObjectStorageWrapper(getContext(), 'userAgent'); const genHeaders = (amount: number) => { const resultHeaders = []; for (let i = 0; i < amount; i++) { resultHeaders.push({ key: `key${i}`, value: `value${i}` }); } return resultHeaders; }; const data = { foo: 'bar', }; const updatedData = { foo: 'bar', bap: 'baz', }; const queryKey = 'baz'; const queryValue = 'bap'; const ttl = 10; const id = 'id123'; const createObjectWithQueriableField = { contentType: 'application/json', createdAt: 1622811501107, objectId: '2bd48165-119f-489d-8842-8d07b2c7cc1b', metadata: {}, queriableFields: { demosearchfield: 'qwerty', }, }; let finalReqCfg; afterEach(sinon.restore); before(() => { process.env.ELASTICIO_FLOW_ID = 'flow_id'; process.env.ELASTICIO_STEP_ID = 'step_id'; }); describe('Create object', () => { beforeEach(async () => { finalReqCfg = sinon.stub(StorageClient.prototype, <any>'requestRetry').callsFake(async () => ({ data: createObjectWithQueriableField })); }); describe('valid inputs', () => { it('Should save the data correctly (1 q-header, ttl-value)', async () => { const result = await objectStorageWrapper.createObject(data, genHeaders(1), [], ttl); expect(result).to.be.equal(createObjectWithQueriableField.objectId); const { firstArg, lastArg } = finalReqCfg.getCall(0); expect(lastArg).to.be.deep.equal({}); const stream = await firstArg.getFreshStream(); expect(await getStream(stream)).to.be.equal(JSON.stringify(data)); expect(firstArg.axiosReqConfig).to.be.deep.equal({ method: 'post', url: '/objects', headers: { Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6I', 'User-Agent': 'userAgent axios/^1.8.2', 'x-query-key0': 'value0', 'x-eio-ttl': '10', 'x-request-id': 'f:flow_id;s:step_id;m:', } }); }); it('Should save the data correctly (2 q-header, 3 q-header)', async () => { const result = await objectStorageWrapper.createObject(data, genHeaders(2), genHeaders(3)); expect(result).to.be.equal(createObjectWithQueriableField.objectId); const { firstArg, lastArg } = finalReqCfg.getCall(0); expect(lastArg).to.be.deep.equal({}); const stream = await firstArg.getFreshStream(); expect(await getStream(stream)).to.be.equal(JSON.stringify(data)); expect(firstArg.axiosReqConfig).to.be.deep.equal({ method: 'post', url: '/objects', headers: { Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6I', 'User-Agent': 'userAgent axios/^1.8.2', 'x-query-key0': 'value0', 'x-query-key1': 'value1', 'x-meta-key0': 'value0', 'x-meta-key1': 'value1', 'x-meta-key2': 'value2', 'x-request-id': 'f:flow_id;s:step_id;m:', } }); }); it('Should save the data correctly (no headers)', async () => { const result = await objectStorageWrapper.createObject(data); expect(result).to.be.equal(createObjectWithQueriableField.objectId); const { firstArg, lastArg } = finalReqCfg.getCall(0); expect(lastArg).to.be.deep.equal({}); const stream = await firstArg.getFreshStream(); expect(await getStream(stream)).to.be.equal(JSON.stringify(data)); expect(firstArg.axiosReqConfig).to.be.deep.equal({ method: 'post', url: '/objects', headers: { Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6I', 'User-Agent': 'userAgent axios/^1.8.2', 'x-request-id': 'f:flow_id;s:step_id;m:', } }); }); it('Should save the data correctly (no headers)', async () => { const result = await objectStorageWrapper.createObject(data, [], []); expect(result).to.be.equal(createObjectWithQueriableField.objectId); const { firstArg, lastArg } = finalReqCfg.getCall(0); expect(lastArg).to.be.deep.equal({}); const stream = await firstArg.getFreshStream(); expect(await getStream(stream)).to.be.equal(JSON.stringify(data)); expect(firstArg.axiosReqConfig).to.be.deep.equal({ method: 'post', url: '/objects', headers: { Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6I', 'User-Agent': 'userAgent axios/^1.8.2', 'x-request-id': 'f:flow_id;s:step_id;m:', } }); }); }); describe('invalid inputs', () => { it('Should throw error', async () => { await expect( // @ts-ignore objectStorageWrapper.createObject(data, [{ key: 'key0', value: 'value0' }, { key: 'key1' }], [], ttl) ).to.be.rejectedWith('header "value" is mandatory if header "key" passed'); }); it('Should throw error', async () => { await expect( // @ts-ignore objectStorageWrapper.createObject(data, [{ value: 'value1' }], [], ttl) ).to.be.rejectedWith('header "key" is mandatory if header "value" passed'); }); it(`Should throw error, Maester headers maximum amount is exceed (${MAESTER_MAX_SUPPORTED_COUNT_OF_QUERY_HEADERS} items)`, async () => { await expect( // @ts-ignore objectStorageWrapper.createObject(data, genHeaders(MAESTER_MAX_SUPPORTED_COUNT_OF_QUERY_HEADERS + 1), [], ttl) ).to.be.rejectedWith(`maximum available amount of headers is ${MAESTER_MAX_SUPPORTED_COUNT_OF_QUERY_HEADERS}`); }); it('Should throw error, Header used more than one time', async () => { await expect( // @ts-ignore objectStorageWrapper.createObject( data, [ { key: 'key0', value: 'value0' }, { key: 'key1', value: 'value0' }, { key: 'key0', value: 'value0' }, ], [], ttl, ) ).to.be.rejectedWith('header key "key0" was already added'); }); }); }); describe('Lookup object by ID', () => { beforeEach(async () => { finalReqCfg = sinon.stub(StorageClient.prototype, <any>'requestRetry').callsFake(async () => ({ data: streamFromObject(data) })); }); it('Should successfully return object', async () => { const result = await objectStorageWrapper.lookupObjectById(id); expect(result).to.be.deep.equal(data); const { firstArg, lastArg } = finalReqCfg.getCall(0); expect(lastArg).to.be.deep.equal({}); expect(firstArg.getFreshStream).to.be.equal(undefined); expect(firstArg.axiosReqConfig).to.deep.equal({ method: 'get', url: '/objects/id123', responseType: 'stream', params: {}, headers: { Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6I', 'User-Agent': 'userAgent axios/^1.8.2', 'x-request-id': 'f:flow_id;s:step_id;m:', } }); }); }); describe('Lookup objects by query parameters', () => { beforeEach(async () => { finalReqCfg = sinon.stub(StorageClient.prototype, <any>'requestRetry').callsFake(async () => ({ data: streamFromObject([createObjectWithQueriableField, createObjectWithQueriableField]) })); }); it('Should return 2 objects', async () => { const result = await objectStorageWrapper.lookupObjectsByQueryParameters([{ key: queryKey, value: queryValue }]); expect(result).to.deep.equal([createObjectWithQueriableField, createObjectWithQueriableField]); const { firstArg, lastArg } = finalReqCfg.getCall(0); expect(lastArg).to.be.deep.equal({}); expect(firstArg.getFreshStream).to.be.equal(undefined); expect(firstArg.axiosReqConfig).to.deep.equal({ method: 'get', url: '/objects', responseType: 'stream', params: { 'query[baz]': 'bap' }, headers: { Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6I', 'User-Agent': 'userAgent axios/^1.8.2', 'x-request-id': 'f:flow_id;s:step_id;m:', } }); }); it('Should throw error: query key set, query value undefined', async () => { await expect( // @ts-ignore objectStorageWrapper.lookupObjectsByQueryParameters([{ key: 'key0', value: 'value0' }, { key: 'key1' }]) ).to.be.rejectedWith('header "value" is mandatory if header "key" passed'); }); }); describe('Update object', () => { beforeEach(async () => { finalReqCfg = sinon.stub(StorageClient.prototype, <any>'requestRetry').callsFake(async () => ({ data: createObjectWithQueriableField })); }); describe('Valid update request', () => { it('Should successfully update an object', async () => { const result = await objectStorageWrapper.updateObjectById(id, updatedData); expect(result).to.deep.equal(createObjectWithQueriableField); const { firstArg, lastArg } = finalReqCfg.getCall(0); expect(lastArg).to.be.deep.equal({}); const stream = await firstArg.getFreshStream(); expect(await getStream(stream)).to.be.equal(JSON.stringify(updatedData)); expect(firstArg.axiosReqConfig).to.be.deep.equal({ method: 'put', url: '/objects/id123', headers: { Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6I', 'User-Agent': 'userAgent axios/^1.8.2', 'x-request-id': 'f:flow_id;s:step_id;m:', } }); }); it('Should successfully update an object with headers', async () => { const result = await objectStorageWrapper.updateObjectById(id, updatedData, genHeaders(3), genHeaders(2)); expect(result).to.deep.equal(createObjectWithQueriableField); const { firstArg, lastArg } = finalReqCfg.getCall(0); expect(lastArg).to.be.deep.equal({}); const stream = await firstArg.getFreshStream(); expect(await getStream(stream)).to.be.equal(JSON.stringify(updatedData)); expect(firstArg.axiosReqConfig).to.be.deep.equal({ method: 'put', url: '/objects/id123', headers: { Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6I', 'User-Agent': 'userAgent axios/^1.8.2', 'x-query-key0': 'value0', 'x-query-key1': 'value1', 'x-query-key2': 'value2', 'x-meta-key0': 'value0', 'x-meta-key1': 'value1', 'x-request-id': 'f:flow_id;s:step_id;m:', } }); }); }); describe('Invalid update request', () => { it('Should throw an error', async () => { await expect( // @ts-ignore objectStorageWrapper.updateObjectById( id, updatedData, [ { key: 'key0', value: 'value0' }, { key: 'key0', value: 'value0' }, ], ) ).to.be.rejectedWith('header key "key0" was already added'); }); }); }); describe('Delete object by ID', () => { beforeEach(async () => { finalReqCfg = sinon.stub(StorageClient.prototype, <any>'requestRetry').callsFake(async () => ({ data: '' })); }); it('should delete object by ID', async () => { const objectStorageWrapper2 = new ObjectStorageWrapper(getContext(), 'userAgent', 'msgId'); const result = await objectStorageWrapper2.deleteObjectById(id); expect(result.data).to.be.equal(''); const { firstArg, lastArg } = finalReqCfg.getCall(0); expect(lastArg).to.be.deep.equal({}); expect(firstArg.getFreshStream).to.be.equal(undefined); expect(firstArg.axiosReqConfig).to.be.deep.equal({ method: 'delete', url: '/objects/id123', params: {}, headers: { Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6I', 'User-Agent': 'userAgent axios/^1.8.2', 'x-request-id': 'f:flow_id;s:step_id;m:msgId', } }); }); }); describe('Delete object by query parameter', () => { beforeEach(async () => { finalReqCfg = sinon.stub(StorageClient.prototype, <any>'requestRetry').callsFake(async () => ({ data: '' })); }); describe('Different amount of search params', () => { describe('valid input', () => { it('Should successfully delete objects (one param)', async () => { const result = await objectStorageWrapper.deleteObjectsByQueryParameters(genHeaders(2)); expect(result.data).to.be.equal(''); const { firstArg, lastArg } = finalReqCfg.getCall(0); expect(lastArg).to.be.deep.equal({}); expect(firstArg.getFreshStream).to.be.equal(undefined); expect(firstArg.axiosReqConfig).to.be.deep.equal({ method: 'delete', url: '/objects', params: { 'query[key0]': 'value0', 'query[key1]': 'value1' }, headers: { Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6I', 'User-Agent': 'userAgent axios/^1.8.2', 'x-request-id': 'f:flow_id;s:step_id;m:', } }); }); }); }); }); });