@elastic.io/maester-client
Version:
The official object-storage client
333 lines (332 loc) • 19.3 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = __importStar(require("chai"));
const axios_1 = __importDefault(require("axios"));
const sinon_1 = __importDefault(require("sinon"));
const fs_1 = __importDefault(require("fs"));
const common_1 = require("./common");
const utils = __importStar(require("../src/utils"));
const logger_1 = __importDefault(require("../src/logger"));
const src_1 = require("../src");
const errors_1 = require("../src/errors");
chai_1.default.use(require('chai-as-promised'));
describe('objectStorage', () => {
const objectStorage = new src_1.ObjectStorage(common_1.creds);
describe('add', () => {
describe('as stream', () => {
it('should add (image)', async () => {
const getAttachAsStream = async () => (await axios_1.default.get('https://if0s.info/files/1.jpg', { responseType: 'stream' })).data;
const objectId = await objectStorage.add(getAttachAsStream);
(0, chai_1.expect)(typeof objectId).to.be.equal('string');
});
it('should add (pdf)', async () => {
const getAttachAsStream = async () => (await axios_1.default.get('http://environmentclearance.nic.in/writereaddata/FormB/Agenda/2201201642EWMJ8Bpdf18.pdf', { responseType: 'stream' })).data;
const objectId = await objectStorage.add(getAttachAsStream);
(0, chai_1.expect)(typeof objectId).to.be.equal('string');
});
it('should add (json file)', async () => {
const getAttachAsStream = async () => (await axios_1.default.get('https://raw.githubusercontent.com/elasticio/jsonata-transform-component/master/package-lock.json', { responseType: 'stream' })).data;
const objectId = await objectStorage.add(getAttachAsStream);
(0, chai_1.expect)(typeof objectId).to.be.equal('string');
});
it('should add (json)', async () => {
const getJSONAsStream = async () => utils.streamFromData({ a: 4 });
const objectId = await objectStorage.add(getJSONAsStream);
(0, chai_1.expect)(typeof objectId).to.be.equal('string');
const { data } = await objectStorage.getOne(objectId);
(0, chai_1.expect)(data).to.be.deep.equal({ data: { a: 4 }, headers: {} });
});
});
describe('as any', () => {
it('should add (JSON)', async () => {
const objectId = await objectStorage.add({ a: 2 });
(0, chai_1.expect)(typeof objectId).to.be.equal('string');
const { data } = await objectStorage.getOne(objectId);
(0, chai_1.expect)(data).to.be.deep.equal({ a: 2 });
const objectHeaders = await objectStorage.getHeaders(objectId);
(0, chai_1.expect)(objectHeaders['content-type']).to.be.equal('application/json');
});
it('should add array', async () => {
const dataArray = [1, '2', null, { d: 2, a: 1 }];
const objectId = await objectStorage.add(dataArray);
(0, chai_1.expect)(typeof objectId).to.be.equal('string');
const { data } = await objectStorage.getOne(objectId);
(0, chai_1.expect)(data).to.be.deep.equal(dataArray);
const objectHeaders = await objectStorage.getHeaders(objectId);
(0, chai_1.expect)(objectHeaders['content-type']).to.be.equal('application/json');
});
it('should add string', async () => {
const dataString = 'hurray';
const objectId = await objectStorage.add(dataString);
(0, chai_1.expect)(typeof objectId).to.be.equal('string');
const { data } = await objectStorage.getOne(objectId);
(0, chai_1.expect)(data).to.be.deep.equal(dataString);
const objectHeaders = await objectStorage.getHeaders(objectId);
(0, chai_1.expect)(objectHeaders['content-type']).to.be.equal('application/json');
});
it('should add number', async () => {
const dataNumber = 56;
const objectId = await objectStorage.add(dataNumber);
(0, chai_1.expect)(typeof objectId).to.be.equal('string');
const { data } = await objectStorage.getOne(objectId);
(0, chai_1.expect)(data).to.be.deep.equal(dataNumber);
const objectHeaders = await objectStorage.getHeaders(objectId);
(0, chai_1.expect)(objectHeaders['content-type']).to.be.equal('application/json');
});
it('should add null', async () => {
const objectId = await objectStorage.add(null);
(0, chai_1.expect)(typeof objectId).to.be.equal('string');
const { data } = await objectStorage.getOne(objectId);
(0, chai_1.expect)(data).to.be.deep.equal(null);
const objectHeaders = await objectStorage.getHeaders(objectId);
(0, chai_1.expect)(objectHeaders['content-type']).to.be.equal('application/json');
});
it('BE AWARE (undefined turns into null, because of JSON.stringify)', async () => {
const dataArrayIn = [1, '2', undefined, null, { d: 2, a: 1 }];
const dataArrayOut = [1, '2', null, null, { d: 2, a: 1 }];
const objectId = await objectStorage.add(dataArrayIn);
(0, chai_1.expect)(typeof objectId).to.be.equal('string');
const { data } = await objectStorage.getOne(objectId);
(0, chai_1.expect)(data).to.be.deep.equal(dataArrayOut);
const objectHeaders = await objectStorage.getHeaders(objectId);
(0, chai_1.expect)(objectHeaders['content-type']).to.be.equal('application/json');
});
});
describe('with custom headers', () => {
it('should add with custom headers', async () => {
const objectId = await objectStorage.add({ a: 2 }, {
headers: {
'content-type': 'some-type',
'x-eio-ttl': 1,
'x-meta-k': 'v',
'x-query-k': 'v',
}
});
(0, chai_1.expect)(typeof objectId).to.be.equal('string');
const { data } = await objectStorage.getOne(objectId);
(0, chai_1.expect)(data).to.be.deep.equal({ a: 2 });
const objectWithHeaders = await objectStorage.getHeaders(objectId);
(0, chai_1.expect)(objectWithHeaders['content-type']).to.be.equal('some-type');
(0, chai_1.expect)(objectWithHeaders['x-meta-k']).to.be.equal('v');
(0, chai_1.expect)(objectWithHeaders['x-query-k']).to.be.equal('v');
});
});
});
describe('get', () => {
it('should get (default responseType: json)', async () => {
const objectId = await objectStorage.add({ a: 2 });
const { data } = await objectStorage.getOne(objectId);
(0, chai_1.expect)(data).to.be.deep.equal({ a: 2 });
});
it('should get (default responseType: json)', async () => {
const getJSONAsStream = async () => utils.streamFromData({ a: 4 });
const objectId = await objectStorage.add(getJSONAsStream);
const { data } = await objectStorage.getOne(objectId);
(0, chai_1.expect)(data).to.be.deep.equal({ a: 4 });
});
it('should throw error (get image as json)', async () => {
const getAttachAsStream = async () => (await axios_1.default.get('https://if0s.info/files/1.jpg', { responseType: 'stream' })).data;
const objectId = await objectStorage.add(getAttachAsStream);
await (0, chai_1.expect)(objectStorage.getOne(objectId)).to.be.rejectedWith('Could not parse Maester object as it is not a JSON object');
});
xit('should get (default responseType: json)', async () => {
const getAttachAsStream = async () => (await axios_1.default.get('https://if0s.info/files/1.jpg', { responseType: 'stream' })).data;
const objectId = await objectStorage.add(getAttachAsStream);
const stream = await objectStorage.getOne(objectId, { responseType: 'stream' });
stream.pipe(fs_1.default.createWriteStream('./a.png'));
});
});
describe('update', () => {
it('should update (addAsJSON, update as stream)', async () => {
const dataAsStream = async () => utils.streamFromData({ a: 2 });
const objId = await objectStorage.add({ a: 3 });
const resUpdate = await objectStorage.update(objId, dataAsStream);
const { data } = await objectStorage.getOne(objId);
(0, chai_1.expect)(data).to.be.deep.equal({ a: 2 });
(0, chai_1.expect)(resUpdate.contentType).to.be.equal('application/json');
});
it('should update (addAsJSON, update as json)', async () => {
const objId = await objectStorage.add({ a: 3 });
const resUpdate = await objectStorage.update(objId, { a: 2 });
const { data } = await objectStorage.getOne(objId);
(0, chai_1.expect)(data).to.be.deep.equal({ a: 2 });
(0, chai_1.expect)(resUpdate.contentType).to.be.equal('application/json');
});
it('should update (addAsStream, update as stream)', async () => {
const dataAsStream = async () => utils.streamFromData({ a: 4 });
const dataAsStream2 = async () => utils.streamFromData({ a: 2 });
const objId = await objectStorage.add(dataAsStream);
await objectStorage.update(objId, dataAsStream2);
const { data } = await objectStorage.getOne(objId);
(0, chai_1.expect)(data).to.be.deep.equal({ a: 2 });
});
it('should update (addAsStream, update as json)', async () => {
const dataAsStream = async () => utils.streamFromData({ a: 4 });
const objId = await objectStorage.add(dataAsStream);
await objectStorage.update(objId, { a: 2 });
const { data } = await objectStorage.getOne(objId);
(0, chai_1.expect)(data).to.be.deep.equal({ a: 2 });
});
it('should update pdf', async () => {
const dataAsStream = async () => utils.streamFromData({ a: 4 });
const objId = await objectStorage.add(dataAsStream);
const getAttachAsStream2 = async () => (await axios_1.default.get('http://www.africau.edu/images/default/sample.pdf', { responseType: 'stream' })).data;
const resUpd = await objectStorage.update(objId, getAttachAsStream2);
(0, chai_1.expect)(resUpd.contentType).to.be.equal('application/pdf');
});
it('should update with custom content-type', async () => {
const objectId = await objectStorage.add({ a: 2 });
await objectStorage.update(objectId, { a: 3 }, { headers: { 'content-type': 'some-type' } });
const { data } = await objectStorage.getOne(objectId);
(0, chai_1.expect)(data).to.be.deep.equal({ a: 3 });
const objectWithHeaders = await objectStorage.getHeaders(objectId);
(0, chai_1.expect)(objectWithHeaders['content-type']).to.be.equal('some-type');
});
});
describe('deleteOne', () => {
it('should deleteOne', async () => {
const getAttachAsStream = async () => utils.streamFromData({ a: 4 });
const objectId = await objectStorage.add(getAttachAsStream);
const deletedObject = await objectStorage.deleteOne(objectId);
(0, chai_1.expect)(deletedObject.data).to.be.equal('');
await (0, chai_1.expect)(objectStorage.getOne(objectId)).to.be.rejectedWith('Request failed with status code 404');
});
});
describe('deleteAllByParams', () => {
it('should deleteAllByParams', async () => {
await objectStorage.add({}, { headers: { 'x-query-t': '123' } });
await objectStorage.add({}, { headers: { 'x-query-t': '123' } });
const aliveId = await objectStorage.add({}, { headers: { 'x-query-t': '1234' } });
const resultBeforeDelete = await objectStorage.getAllByParams({ 'query[t]': '123' });
(0, chai_1.expect)(resultBeforeDelete.length).to.be.equal(2);
await objectStorage.deleteAllByParams({ 'query[t]': '123' });
const resultAfterDelete = await objectStorage.getAllByParams({ 'query[t]': '123' });
(0, chai_1.expect)(resultAfterDelete.length).to.be.equal(0);
const { data: aliveData } = await objectStorage.getOne(aliveId);
(0, chai_1.expect)(aliveData).to.be.deep.equal({});
});
});
describe('getByParams', () => {
it('should getByParams', async () => {
const jsonAsStream = async () => utils.streamFromData({ a: 4 });
const objId1 = await objectStorage.add(jsonAsStream, { headers: { 'x-query-x': '123' } });
const objId2 = await objectStorage.add(jsonAsStream, { headers: { 'x-query-x': '123' } });
const objId3 = await objectStorage.add(jsonAsStream, { headers: { 'x-query-x': '1234' } });
const result = await objectStorage.getAllByParams({ 'query[x]': '123' });
await objectStorage.deleteOne(objId1);
await objectStorage.deleteOne(objId2);
await objectStorage.deleteOne(objId3);
(0, chai_1.expect)(result.length).to.be.equal(2);
});
});
describe('errors handling', () => {
let loggingWarnSpy;
beforeEach(() => {
loggingWarnSpy = sinon_1.default.spy(logger_1.default, 'warn');
});
afterEach(sinon_1.default.restore);
describe('response with error (4xx)', () => {
it('should throw 400, no retries', async () => {
let err;
try {
await objectStorage.getOne('not-a-uuid');
}
catch (error) {
err = error;
}
(0, chai_1.expect)(err.message).to.be.equal('Client error during request: Request failed with status code 400');
(0, chai_1.expect)(err instanceof errors_1.ClientTransportError).to.be.equal(true);
(0, chai_1.expect)(err.code).to.be.equal(400);
});
it('should throw 404, no retries', async () => {
let err;
try {
await objectStorage.getOne('2e084a24-e2ea-47c6-a95a-732ec8df7263');
}
catch (error) {
err = error;
}
(0, chai_1.expect)(err.message).to.be.equal('Client error during request: Request failed with status code 404');
(0, chai_1.expect)(err instanceof errors_1.ClientTransportError).to.be.equal(true);
(0, chai_1.expect)(err.code).to.be.equal(404);
});
});
describe('Server error (5xx)', () => {
beforeEach(() => {
sinon_1.default.stub(utils, 'validateAndGetRetryOptions').callsFake(() => ({ retriesCount: 2, requestTimeout: 1 }));
});
it('should throw 5xx', async () => {
let err;
try {
await objectStorage.getOne('some-id');
}
catch (error) {
err = error;
}
(0, chai_1.expect)(err.message).to.be.equal('Server error during request: "timeout of 1ms exceeded"');
(0, chai_1.expect)(err instanceof errors_1.ServerTransportError).to.be.equal(true);
(0, chai_1.expect)(loggingWarnSpy.callCount).to.be.equal(2);
const [{ err: err1 }, log1] = loggingWarnSpy.getCall(0).args;
(0, chai_1.expect)(err1.toJSON().message).to.be.equal('timeout of 1ms exceeded');
(0, chai_1.expect)(log1).to.be.equal('Error during object request, retrying (1)');
const [{ err: err2 }, log2] = loggingWarnSpy.getCall(1).args;
(0, chai_1.expect)(err2.toJSON().message).to.be.equal('timeout of 1ms exceeded');
(0, chai_1.expect)(log2).to.be.equal('Error during object request, retrying (2)');
});
xit('RUN THIS TEST WITHOUT PORT-FORWARDING', async () => {
let err;
try {
await objectStorage.getOne('some-id');
}
catch (error) {
err = error;
}
(0, chai_1.expect)(err.message).to.be.equal('Server error during request: "connect ECONNREFUSED 127.0.0.1:3002"');
(0, chai_1.expect)(err instanceof errors_1.ServerTransportError).to.be.equal(true);
(0, chai_1.expect)(loggingWarnSpy.callCount).to.be.equal(2);
const [{ err: err1 }, log1] = loggingWarnSpy.getCall(0).args;
(0, chai_1.expect)(err1.toJSON().message).to.be.equal('connect ECONNREFUSED 127.0.0.1:3002');
(0, chai_1.expect)(log1).to.be.equal('Error during object request, retrying (1)');
const [{ err: err2 }, log2] = loggingWarnSpy.getCall(1).args;
(0, chai_1.expect)(err2.toJSON().message).to.be.equal('connect ECONNREFUSED 127.0.0.1:3002');
(0, chai_1.expect)(log2).to.be.equal('Error during object request, retrying (2)');
});
});
});
});