UNPKG

filestack-js

Version:

Official JavaScript library for Filestack

343 lines (341 loc) 43 kB
/* * Copyright (c) 2019 by Filestack. * Some rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { __awaiter, __generator } from "tslib"; import { Upload } from './upload'; import { S3Uploader } from './uploaders/s3'; import { config } from './../../../config'; var testBuffer = Buffer.from('test test test'); var customNameMocked = jest.fn(); var mockedFsFile = {}; Object.defineProperty(mockedFsFile, 'customName', { set: customNameMocked, }); jest.useFakeTimers(); jest.mock('./uploaders/s3'); jest.mock('./file_tools', function () { return ({ getFile: jest.fn().mockImplementation(function () { return mockedFsFile; }), }); }); var mockedFileResponse = { status: 'stored', }; var sessionURls = config.urls; var defaultSession = { apikey: 'test', policy: 'p', signature: 's', urls: sessionURls, }; var mockExecute = jest.fn(); describe('Api/Upload/upload', function () { beforeAll(function () { jest.spyOn(S3Uploader.prototype, 'execute').mockImplementation(mockExecute); }); describe('Settings', function () { it('should handle constructor options', function () { var u = new Upload({ partSize: 5 * 1024 * 1024, intelligentChunkSize: 5 * 1024 * 1024, }); expect(S3Uploader.prototype.setPartSize).toHaveBeenCalledWith(5 * 1024 * 1024); expect(S3Uploader.prototype.setIntelligentChunkSize).toHaveBeenCalledWith(5 * 1024 * 1024); }); it('should throw error on wrong upload options', function () { // @ts-ignore expect(function () { return new Upload({ intelligent1: true }); }).toThrowError('Invalid upload params'); }); it('should accept sanitizer settings', function () { expect(function () { return new Upload({}, { // @ts-ignore sanitizer: false, }); }).not.toThrowError('Invalid upload params'); expect(function () { return new Upload({}, { // @ts-ignore sanitizer: { exclude: ['1'], replacement: '-', }, }); }).not.toThrowError('Invalid upload params'); }); it('should throw error on wrong store options', function () { // @ts-ignore expect(function () { return new Upload({ intelligent: true }, { test: 123 }); }).toThrowError('Invalid store upload params'); }); it('should set intelligent upload mode', function () { var u = new Upload({ intelligent: true }); expect(S3Uploader.prototype.setUploadMode).toHaveBeenCalledWith("intelligent" /* UploadMode.INTELLIGENT */); }); it('should set respect disableIntegrityCheck param', function () { var u = new Upload({ disableIntegrityCheck: true }); expect(S3Uploader.prototype.setIntegrityCheck).toHaveBeenCalledWith(false); }); it('should fallback upload mode', function () { var u = new Upload({ intelligent: 'fallback' }); expect(S3Uploader.prototype.setUploadMode).toHaveBeenCalledWith("fallback" /* UploadMode.FALLBACK */); }); it('should set upload tasks to uploader', function () { var tags = { test: '123' }; var u = new Upload({ tags: tags }); expect(S3Uploader.prototype.setUploadTags).toHaveBeenCalledWith(tags); }); it('should pass store options to uploader class', function () { var storeOptions = { location: 's3', }; var u = new Upload({}, storeOptions); expect(S3Uploader.prototype.constructor).toHaveBeenCalledWith(storeOptions, undefined); }); it('should respect concurrency param in upload options', function () { var uploadOptions = { concurrency: 4, }; var u = new Upload(uploadOptions); expect(S3Uploader.prototype.constructor).toHaveBeenCalledWith({}, 4); }); it('should set correct security to uploader', function () { var security = { policy: 'p', signature: 's', }; var u = new Upload(); u.setSecurity(security); expect(S3Uploader.prototype.setSecurity).toHaveBeenCalledWith(security); }); it('should pass session variable to uploader', function () { var u = new Upload(); u.setSession(defaultSession); expect(S3Uploader.prototype.setUrl).toHaveBeenCalledWith(defaultSession.urls.uploadApiUrl); expect(S3Uploader.prototype.setApikey).toHaveBeenCalledWith(defaultSession.apikey); expect(S3Uploader.prototype.setSecurity).toHaveBeenCalledWith({ policy: defaultSession.policy, signature: defaultSession.signature }); }); it('should set storeOption filename to class', function () { return __awaiter(void 0, void 0, void 0, function () { var filenameFn, u; return __generator(this, function (_a) { switch (_a.label) { case 0: mockExecute.mockReturnValue(Promise.resolve([mockedFileResponse])); filenameFn = function () { return 'test'; }; u = new Upload({}, { filename: filenameFn, }); return [4 /*yield*/, u.upload(testBuffer)]; case 1: _a.sent(); expect(customNameMocked).toHaveBeenCalledWith(filenameFn); return [2 /*return*/]; } }); }); }); it('should assign methods to user provided token', function () { var token = {}; var u = new Upload(); u.setToken(token); expect(token['cancel']).toBeTruthy(); expect(token['resume']).toBeTruthy(); expect(token['pause']).toBeTruthy(); token['cancel'](); token['pause'](); token['resume'](); }); it('should set token with methods that pause,cancel or resume uploads', function () { var token = {}; var u = new Upload(); u.setToken(token); token['cancel'](); token['pause'](); token['resume'](); expect(S3Uploader.prototype.abort).toHaveBeenCalled(); expect(S3Uploader.prototype.pause).toHaveBeenCalled(); expect(S3Uploader.prototype.resume).toHaveBeenCalled(); }); it('should throw an error if token is not an object', function () { var token = '123123'; var u = new Upload(); expect(function () { u.setToken(token); }).toThrowError(); }); }); describe('Upload', function () { beforeEach(function () { mockExecute.mockReturnValue(Promise.resolve([mockedFileResponse, mockedFileResponse])); }); it('should execute normal upload without errors and return single file response', function () { return __awaiter(void 0, void 0, void 0, function () { var u, res; return __generator(this, function (_a) { switch (_a.label) { case 0: u = new Upload(); return [4 /*yield*/, u.upload(testBuffer)]; case 1: res = _a.sent(); expect(res).toEqual(mockedFileResponse); return [2 /*return*/]; } }); }); }); it('should execute normal upload with errors and return rejected promise', function () { var u = new Upload(); mockExecute.mockReturnValue(Promise.resolve([ { status: "Failed" /* FileState.FAILED */, }, ])); return expect(u.upload(testBuffer)).rejects.toEqual({ status: "Failed" /* FileState.FAILED */, }); }); it('should execute multiupload without errors and return single file response', function () { return __awaiter(void 0, void 0, void 0, function () { var u, res; return __generator(this, function (_a) { switch (_a.label) { case 0: u = new Upload(); return [4 /*yield*/, u.multiupload([testBuffer, testBuffer])]; case 1: res = _a.sent(); expect(res).toEqual([mockedFileResponse, mockedFileResponse]); return [2 /*return*/]; } }); }); }); }); describe('Progress', function () { var progress1 = { totalBytes: 1, totalPercent: 1, files: [ { totalBytes: 1, totalPercent: 1, }, ], }; var progress50 = { totalBytes: 5, totalPercent: 50, files: [ { totalBytes: 50, totalPercent: 50, }, ], }; var progress100 = { totalBytes: 100, totalPercent: 100, files: [ { totalBytes: 100, totalPercent: 100, }, ], }; it('should handle correct progress event', function () { return __awaiter(void 0, void 0, void 0, function () { var progressMock, u; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: jest.spyOn(S3Uploader.prototype, 'on').mockImplementation(function (ev, cb) { cb(progress1); cb(progress100); return _this; }); progressMock = jest.fn(); u = new Upload({ onProgress: progressMock, }); return [4 /*yield*/, u.upload(testBuffer)]; case 1: _a.sent(); expect(progressMock).toHaveBeenCalledWith(progress100); expect(progressMock).toHaveBeenCalledTimes(1); return [2 /*return*/]; } }); }); }); it('should call progress event on given interval', function () { return __awaiter(void 0, void 0, void 0, function () { var progressCb, progressMock, u; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: mockExecute.mockImplementation(function () { return new Promise(function (resolve) { setTimeout(function () { return progressCb(progress1); }, 1); setTimeout(function () { return progressCb(progress50); }, 2); setTimeout(function () { return progressCb(progress100); }, 3); setTimeout(function () { return resolve([]); }, 4); jest.advanceTimersByTime(4); }); }); jest.spyOn(S3Uploader.prototype, 'on').mockImplementation(function (ev, cb) { progressCb = cb; return _this; }); progressMock = jest.fn(); u = new Upload({ progressInterval: 1, onProgress: progressMock, }); return [4 /*yield*/, u.multiupload([testBuffer])]; case 1: _a.sent(); expect(progressMock).toHaveBeenCalledWith(progress1); expect(progressMock).toHaveBeenCalledWith(progress50); expect(progressMock).toHaveBeenCalledWith(progress100); return [2 /*return*/]; } }); }); }); it('should stay at the same progress when uploader goes back with file progress', function () { return __awaiter(void 0, void 0, void 0, function () { var progressCb, progressMock, u; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: mockExecute.mockImplementation(function () { return new Promise(function (resolve) { setTimeout(function () { return progressCb(progress50); }, 1); setTimeout(function () { return progressCb(progress1); }, 2); setTimeout(function () { return progressCb(progress100); }, 3); setTimeout(function () { return resolve([]); }, 4); jest.advanceTimersByTime(4); }); }); jest.spyOn(S3Uploader.prototype, 'on').mockImplementation(function (ev, cb) { progressCb = cb; return _this; }); progressMock = jest.fn(); u = new Upload({ progressInterval: 1, onProgress: progressMock, }); return [4 /*yield*/, u.multiupload([testBuffer])]; case 1: _a.sent(); expect(progressMock).toHaveBeenCalledWith(progress50); expect(progressMock).toHaveBeenCalledWith(progress50); expect(progressMock).toHaveBeenCalledWith(progress100); return [2 /*return*/]; } }); }); }); }); }); //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvYXBpL3VwbG9hZC91cGxvYWQuc3BlYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7O0FBRUgsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUVsQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBSTNDLElBQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztBQUVqRCxJQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztBQUVuQyxJQUFNLFlBQVksR0FBRyxFQUFFLENBQUM7QUFDeEIsTUFBTSxDQUFDLGNBQWMsQ0FBQyxZQUFZLEVBQUUsWUFBWSxFQUFFO0lBQ2hELEdBQUcsRUFBRSxnQkFBZ0I7Q0FDdEIsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO0FBRXJCLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztBQUM1QixJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxjQUFNLE9BQUEsQ0FBQztJQUMvQixPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGtCQUFrQixDQUFDLGNBQU0sT0FBQSxZQUFZLEVBQVosQ0FBWSxDQUFDO0NBQzFELENBQUMsRUFGOEIsQ0FFOUIsQ0FBQyxDQUFDO0FBRUosSUFBTSxrQkFBa0IsR0FBRztJQUN6QixNQUFNLEVBQUUsUUFBUTtDQUNqQixDQUFDO0FBRUYsSUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQztBQUNoQyxJQUFNLGNBQWMsR0FBRztJQUNyQixNQUFNLEVBQUUsTUFBTTtJQUNkLE1BQU0sRUFBRSxHQUFHO0lBQ1gsU0FBUyxFQUFFLEdBQUc7SUFDZCxJQUFJLEVBQUUsV0FBVztD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Q0FBQyxVQUFVLENBQUMsQ0FBQzt3QkFDdEQsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLG9CQUFvQixDQUFDLFdBQVcsQ0FBQyxDQUFDOzs7O2FBQ3hELENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJmaWxlIjoibGliL2FwaS91cGxvYWQvdXBsb2FkLnNwZWMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChjKSAyMDE5IGJ5IEZpbGVzdGFjay5cbiAqIFNvbWUgcmlnaHRzIHJlc2VydmVkLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBVcGxvYWQgfSBmcm9tICcuL3VwbG9hZCc7XG5pbXBvcnQgeyBGaWxlU3RhdGUgfSBmcm9tICcuL2ZpbGUnO1xuaW1wb3J0IHsgUzNVcGxvYWRlciB9IGZyb20gJy4vdXBsb2FkZXJzL3MzJztcbmltcG9ydCB7IGNvbmZpZyB9IGZyb20gJy4vLi4vLi4vLi4vY29uZmlnJztcbmltcG9ydCB7IFN0b3JlVXBsb2FkT3B0aW9ucyB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgVXBsb2FkTW9kZSB9IGZyb20gJy4vdXBsb2FkZXJzL2Fic3RyYWN0JztcblxuY29uc3QgdGVzdEJ1ZmZlciA9IEJ1ZmZlci5mcm9tKCd0ZXN0IHRlc3QgdGVzdCcpO1xuXG5jb25zdCBjdXN0b21OYW1lTW9ja2VkID0gamVzdC5mbigpO1xuXG5jb25zdCBtb2NrZWRGc0ZpbGUgPSB7fTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2NrZWRGc0ZpbGUsICdjdXN0b21OYW1lJywge1xuICBzZXQ6IGN1c3RvbU5hbWVNb2NrZWQsXG59KTtcblxuamVzdC51c2VGYWtlVGltZXJzKCk7XG5cbmplc3QubW9jaygnLi91cGxvYWRlcnMvczMnKTtcbmplc3QubW9jaygnLi9maWxlX3Rvb2xzJywgKCkgPT4gKHtcbiAgZ2V0RmlsZTogamVzdC5mbigpLm1vY2tJbXBsZW1lbnRhdGlvbigoKSA9PiBtb2NrZWRGc0ZpbGUpLFxufSkpO1xuXG5jb25zdCBtb2NrZWRGaWxlUmVzcG9uc2UgPSB7XG4gIHN0YXR1czogJ3N0b3JlZCcsXG59O1xuXG5jb25zdCBzZXNzaW9uVVJscyA9IGNvbmZpZy51cmxzO1xuY29uc3QgZGVmYXVsdFNlc3Npb24gPSB7XG4gIGFwaWtleTogJ3Rlc3QnLFxuICBwb2xpY3k6ICdwJyxcbiAgc2lnbmF0dXJlOiAncycsXG4gIHVybHM6IHNlc3Npb25VUmxzLFxufTtcblxuY29uc3QgbW9ja0V4ZWN1dGUgPSBqZXN0LmZuKCk7XG5cbmRlc2NyaWJlKCdBcGkvVXBsb2FkL3VwbG9hZCcsICgpID0+IHtcbiAgYmVmb3JlQWxsKCgpID0+IHtcbiAgICBqZXN0LnNweU9uKFMzVXBsb2FkZXIucHJvdG90eXBlLCAnZXhlY3V0ZScpLm1vY2tJbXBsZW1lbnRhdGlvbihtb2NrRXhlY3V0ZSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdTZXR0aW5ncycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBjb25zdHJ1Y3RvciBvcHRpb25zJywgKCkgPT4ge1xuICAgICAgY29uc3QgdSA9IG5ldyBVcGxvYWQoe1xuICAgICAgICBwYXJ0U2l6ZTogNSAqIDEwMjQgKiAxMDI0LFxuICAgICAgICBpbnRlbGxpZ2VudENodW5rU2l6ZTogNSAqIDEwMjQgKiAxMDI0LFxuICAgICAgfSk7XG5cbiAgICAgIGV4cGVjdChTM1VwbG9hZGVyLnByb3RvdHlwZS5zZXRQYXJ0U2l6ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoNSAqIDEwMjQgKiAxMDI0KTtcbiAgICAgIGV4cGVjdChTM1VwbG9hZGVyLnByb3RvdHlwZS5zZXRJbnRlbGxpZ2VudENodW5rU2l6ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoNSAqIDEwMjQgKiAxMDI0KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igb24gd3JvbmcgdXBsb2FkIG9wdGlvbnMnLCAoKSA9PiB7XG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICBleHBlY3QoKCkgPT4gbmV3IFVwbG9hZCh7IGludGVsbGlnZW50MTogdHJ1ZSB9KSkudG9UaHJvd0Vycm9yKCdJbnZhbGlkIHVwbG9hZCBwYXJhbXMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYWNjZXB0IHNhbml0aXplciBzZXR0aW5ncycsICgpID0+IHtcbiAgICAgIGV4cGVjdCgoKSA9PiBuZXcgVXBsb2FkKHt9LCB7XG4gICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgc2FuaXRpemVyOiBmYWxzZSxcbiAgICAgIH0pKS5ub3QudG9UaHJvd0Vycm9yKCdJbnZhbGlkIHVwbG9hZCBwYXJhbXMnKTtcblxuICAgICAgZXhwZWN0KCgpID0+IG5ldyBVcGxvYWQoe30sIHtcbiAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICBzYW5pdGl6ZXI6IHtcbiAgICAgICAgICBleGNsdWRlOiBbJzEnXSxcbiAgICAgICAgICByZXBsYWNlbWVudDogJy0nLFxuICAgICAgICB9LFxuICAgICAgfSkpLm5vdC50b1Rocm93RXJyb3IoJ0ludmFsaWQgdXBsb2FkIHBhcmFtcycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBvbiB3cm9uZyBzdG9yZSBvcHRpb25zJywgKCkgPT4ge1xuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgZXhwZWN0KCgpID0+IG5ldyBVcGxvYWQoeyBpbnRlbGxpZ2VudDogdHJ1ZSB9LCB7IHRlc3Q6IDEyMyB9KSkudG9UaHJvd0Vycm9yKCdJbnZhbGlkIHN0b3JlIHVwbG9hZCBwYXJhbXMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2V0IGludGVsbGlnZW50IHVwbG9hZCBtb2RlJywgKCkgPT4ge1xuICAgICAgY29uc3QgdSA9IG5ldyBVcGxvYWQoeyBpbnRlbGxpZ2VudDogdHJ1ZSB9KTtcbiAgICAgIGV4cGVjdChTM1VwbG9hZGVyLnByb3RvdHlwZS5zZXRVcGxvYWRNb2RlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChVcGxvYWRNb2RlLklOVEVMTElHRU5UKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2V0IHJlc3BlY3QgZGlzYWJsZUludGVncml0eUNoZWNrIHBhcmFtJywgKCkgPT4ge1xuICAgICAgY29uc3QgdSA9IG5ldyBVcGxvYWQoeyBkaXNhYmxlSW50ZWdyaXR5Q2hlY2s6IHRydWUgfSk7XG4gICAgICBleHBlY3QoUzNVcGxvYWRlci5wcm90b3R5cGUuc2V0SW50ZWdyaXR5Q2hlY2spLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFsbGJhY2sgdXBsb2FkIG1vZGUnLCAoKSA9PiB7XG4gICAgICBjb25zdCB1ID0gbmV3IFVwbG9hZCh7IGludGVsbGlnZW50OiAnZmFsbGJhY2snIH0pO1xuICAgICAgZXhwZWN0KFMzVXBsb2FkZXIucHJvdG90eXBlLnNldFVwbG9hZE1vZGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFVwbG9hZE1vZGUuRkFMTEJBQ0spO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzZXQgdXBsb2FkIHRhc2tzIHRvIHVwbG9hZGVyJywgKCkgPT4ge1xuICAgICAgY29uc3QgdGFncyA9IHsgdGVzdDogJzEyMycgfTtcbiAgICAgIGNvbnN0IHUgPSBuZXcgVXBsb2FkKHsgdGFnczogdGFncyB9KTtcbiAgICAgIGV4cGVjdChTM1VwbG9hZGVyLnByb3RvdHlwZS5zZXRVcGxvYWRUYWdzKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh0YWdzKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcGFzcyBzdG9yZSBvcHRpb25zIHRvIHVwbG9hZGVyIGNsYXNzJywgKCkgPT4ge1xuICAgICAgY29uc3Qgc3RvcmVPcHRpb25zOiBTdG9yZVVwbG9hZE9wdGlvbnMgPSB7XG4gICAgICAgIGxvY2F0aW9uOiAnczMnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdSA9IG5ldyBVcGxvYWQoe30sIHN0b3JlT3B0aW9ucyk7XG4gICAgICBleHBlY3QoUzNVcGxvYWRlci5wcm90b3R5cGUuY29uc3RydWN0b3IpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHN0b3JlT3B0aW9ucywgdW5kZWZpbmVkKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVzcGVjdCBjb25jdXJyZW5jeSBwYXJhbSBpbiB1cGxvYWQgb3B0aW9ucycsICgpID0+IHtcbiAgICAgIGNvbnN0IHVwbG9hZE9wdGlvbnMgPSB7XG4gICAgICAgIGNvbmN1cnJlbmN5OiA0LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdSA9IG5ldyBVcGxvYWQodXBsb2FkT3B0aW9ucyk7XG4gICAgICBleHBlY3QoUzNVcGxvYWRlci5wcm90b3R5cGUuY29uc3RydWN0b3IpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHt9LCA0KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2V0IGNvcnJlY3Qgc2VjdXJpdHkgdG8gdXBsb2FkZXInLCAoKSA9PiB7XG4gICAgICBjb25zdCBzZWN1cml0eSA9IHtcbiAgICAgICAgcG9saWN5OiAncCcsXG4gICAgICAgIHNpZ25hdHVyZTogJ3MnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdSA9IG5ldyBVcGxvYWQoKTtcbiAgICAgIHUuc2V0U2VjdXJpdHkoc2VjdXJpdHkpO1xuXG4gICAgICBleHBlY3QoUzNVcGxvYWRlci5wcm90b3R5cGUuc2V0U2VjdXJpdHkpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHNlY3VyaXR5KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcGFzcyBzZXNzaW9uIHZhcmlhYmxlIHRvIHVwbG9hZGVyJywgKCkgPT4ge1xuICAgICAgY29uc3QgdSA9IG5ldyBVcGxvYWQoKTtcbiAgICAgIHUuc2V0U2Vzc2lvbihkZWZhdWx0U2Vzc2lvbik7XG5cbiAgICAgIGV4cGVjdChTM1VwbG9hZGVyLnByb3RvdHlwZS5zZXRVcmwpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGRlZmF1bHRTZXNzaW9uLnVybHMudXBsb2FkQXBpVXJsKTtcbiAgICAgIGV4cGVjdChTM1VwbG9hZGVyLnByb3RvdHlwZS5zZXRBcGlrZXkpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGRlZmF1bHRTZXNzaW9uLmFwaWtleSk7XG4gICAgICBleHBlY3QoUzNVcGxvYWRlci5wcm90b3R5cGUuc2V0U2VjdXJpdHkpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHsgcG9saWN5OiBkZWZhdWx0U2Vzc2lvbi5wb2xpY3ksIHNpZ25hdHVyZTogZGVmYXVsdFNlc3Npb24uc2lnbmF0dXJlIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzZXQgc3RvcmVPcHRpb24gZmlsZW5hbWUgdG8gY2xhc3MnLCBhc3luYyAoKSA9PiB7XG4gICAgICBtb2NrRXhlY3V0ZS5tb2NrUmV0dXJuVmFsdWUoUHJvbWlzZS5yZXNvbHZlKFttb2NrZWRGaWxlUmVzcG9uc2VdKSk7XG4gICAgICBjb25zdCBmaWxlbmFtZUZuID0gKCkgPT4gJ3Rlc3QnO1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFVwbG9hZChcbiAgICAgICAge30sXG4gICAgICAgIHtcbiAgICAgICAgICBmaWxlbmFtZTogZmlsZW5hbWVGbixcbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgYXdhaXQgdS51cGxvYWQodGVzdEJ1ZmZlcik7XG4gICAgICBleHBlY3QoY3VzdG9tTmFtZU1vY2tlZCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZmlsZW5hbWVGbik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGFzc2lnbiBtZXRob2RzIHRvIHVzZXIgcHJvdmlkZWQgdG9rZW4nLCAoKSA9PiB7XG4gICAgICBsZXQgdG9rZW4gPSB7fTtcblxuICAgICAgY29uc3QgdSA9IG5ldyBVcGxvYWQoKTtcbiAgICAgIHUuc2V0VG9rZW4odG9rZW4pO1xuXG4gICAgICBleHBlY3QodG9rZW5bJ2NhbmNlbCddKS50b0JlVHJ1dGh5KCk7XG4gICAgICBleHBlY3QodG9rZW5bJ3Jlc3VtZSddKS50b0JlVHJ1dGh5KCk7XG4gICAgICBleHBlY3QodG9rZW5bJ3BhdXNlJ10pLnRvQmVUcnV0aHkoKTtcblxuICAgICAgdG9rZW5bJ2NhbmNlbCddKCk7XG4gICAgICB0b2tlblsncGF1c2UnXSgpO1xuICAgICAgdG9rZW5bJ3Jlc3VtZSddKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNldCB0b2tlbiB3aXRoIG1ldGhvZHMgdGhhdCBwYXVzZSxjYW5jZWwgb3IgcmVzdW1lIHVwbG9hZHMnLCAoKSA9PiB7XG4gICAgICBsZXQgdG9rZW4gPSB7fTtcblxuICAgICAgY29uc3QgdSA9IG5ldyBVcGxvYWQoKTtcbiAgICAgIHUuc2V0VG9rZW4odG9rZW4pO1xuXG4gICAgICB0b2tlblsnY2FuY2VsJ10oKTtcbiAgICAgIHRva2VuWydwYXVzZSddKCk7XG4gICAgICB0b2tlblsncmVzdW1lJ10oKTtcblxuICAgICAgZXhwZWN0KFMzVXBsb2FkZXIucHJvdG90eXBlLmFib3J0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICBleHBlY3QoUzNVcGxvYWRlci5wcm90b3R5cGUucGF1c2UpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgIGV4cGVjdChTM1VwbG9hZGVyLnByb3RvdHlwZS5yZXN1bWUpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgYW4gZXJyb3IgaWYgdG9rZW4gaXMgbm90IGFuIG9iamVjdCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHRva2VuID0gJzEyMzEyMyc7XG5cbiAgICAgIGNvbnN0IHUgPSBuZXcgVXBsb2FkKCk7XG4gICAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgICB1LnNldFRva2VuKHRva2VuKTtcbiAgICAgIH0pLnRvVGhyb3dFcnJvcigpO1xuICAgIH0pO1xuXG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdVcGxvYWQnLCAoKSA9PiB7XG4gICAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgICBtb2NrRXhlY3V0ZS5tb2NrUmV0dXJuVmFsdWUoUHJvbWlzZS5yZXNvbHZlKFttb2NrZWRGaWxlUmVzcG9uc2UsIG1vY2tlZEZpbGVSZXNwb25zZV0pKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhlY3V0ZSBub3JtYWwgdXBsb2FkIHdpdGhvdXQgZXJyb3JzIGFuZCByZXR1cm4gc2luZ2xlIGZpbGUgcmVzcG9uc2UnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB1ID0gbmV3IFVwbG9hZCgpO1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS51cGxvYWQodGVzdEJ1ZmZlcik7XG4gICAgICBleHBlY3QocmVzKS50b0VxdWFsKG1vY2tlZEZpbGVSZXNwb25zZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGV4ZWN1dGUgbm9ybWFsIHVwbG9hZCB3aXRoIGVycm9ycyBhbmQgcmV0dXJuIHJlamVjdGVkIHByb21pc2UnLCAoKSA9PiB7XG4gICAgICBjb25zdCB1ID0gbmV3IFVwbG9hZCgpO1xuXG4gICAgICBtb2NrRXhlY3V0ZS5tb2NrUmV0dXJuVmFsdWUoXG4gICAgICAgIFByb21pc2UucmVzb2x2ZShbXG4gICAgICAgICAge1xuICAgICAgICAgICAgc3RhdHVzOiBGaWxlU3RhdGUuRkFJTEVELFxuICAgICAgICAgIH0sXG4gICAgICAgIF0pXG4gICAgICApO1xuXG4gICAgICByZXR1cm4gZXhwZWN0KHUudXBsb2FkKHRlc3RCdWZmZXIpKS5yZWplY3RzLnRvRXF1YWwoe1xuICAgICAgICBzdGF0dXM6IEZpbGVTdGF0ZS5GQUlMRUQsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhlY3V0ZSBtdWx0aXVwbG9hZCB3aXRob3V0IGVycm9ycyBhbmQgcmV0dXJuIHNpbmdsZSBmaWxlIHJlc3BvbnNlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdSA9IG5ldyBVcGxvYWQoKTtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUubXVsdGl1cGxvYWQoW3Rlc3RCdWZmZXIsIHRlc3RCdWZmZXJdKTtcbiAgICAgIGV4cGVjdChyZXMpLnRvRXF1YWwoW21vY2tlZEZpbGVSZXNwb25zZSwgbW9ja2VkRmlsZVJlc3BvbnNlXSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdQcm9ncmVzcycsICgpID0+IHtcbiAgICBjb25zdCBwcm9ncmVzczEgPSB7XG4gICAgICB0b3RhbEJ5dGVzOiAxLFxuICAgICAgdG90YWxQZXJjZW50OiAxLFxuICAgICAgZmlsZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHRvdGFsQnl0ZXM6IDEsXG4gICAgICAgICAgdG90YWxQZXJjZW50OiAxLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuXG4gICAgY29uc3QgcHJvZ3Jlc3M1MCA9IHtcbiAgICAgIHRvdGFsQnl0ZXM6IDUsXG4gICAgICB0b3RhbFBlcmNlbnQ6IDUwLFxuICAgICAgZmlsZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHRvdGFsQnl0ZXM6IDUwLFxuICAgICAgICAgIHRvdGFsUGVyY2VudDogNTAsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG5cbiAgICBjb25zdCBwcm9ncmVzczEwMCA9IHtcbiAgICAgIHRvdGFsQnl0ZXM6IDEwMCxcbiAgICAgIHRvdGFsUGVyY2VudDogMTAwLFxuICAgICAgZmlsZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHRvdGFsQnl0ZXM6IDEwMCxcbiAgICAgICAgICB0b3RhbFBlcmNlbnQ6IDEwMCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcblxuICAgIGl0KCdzaG91bGQgaGFuZGxlIGNvcnJlY3QgcHJvZ3Jlc3MgZXZlbnQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBqZXN0LnNweU9uKFMzVXBsb2FkZXIucHJvdG90eXBlLCAnb24nKS5tb2NrSW1wbGVtZW50YXRpb24oKGV2LCBjYikgPT4ge1xuICAgICAgICBjYihwcm9ncmVzczEpO1xuICAgICAgICBjYihwcm9ncmVzczEwMCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHByb2dyZXNzTW9jayA9IGplc3QuZm4oKTtcblxuICAgICAgY29uc3QgdSA9IG5ldyBVcGxvYWQoe1xuICAgICAgICBvblByb2dyZXNzOiBwcm9ncmVzc01vY2ssXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgdS51cGxvYWQodGVzdEJ1ZmZlcik7XG5cbiAgICAgIGV4cGVjdChwcm9ncmVzc01vY2spLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHByb2dyZXNzMTAwKTtcbiAgICAgIGV4cGVjdChwcm9ncmVzc01vY2spLnRvSGF2ZUJlZW5DYWxsZWRUaW1lcygxKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY2FsbCBwcm9ncmVzcyBldmVudCBvbiBnaXZlbiBpbnRlcnZhbCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGxldCBwcm9ncmVzc0NiO1xuXG4gICAgICBtb2NrRXhlY3V0ZS5tb2NrSW1wbGVtZW50YXRpb24oKCkgPT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiBwcm9ncmVzc0NiKHByb2dyZXNzMSksIDEpO1xuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gcHJvZ3Jlc3NDYihwcm9ncmVzczUwKSwgMik7XG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiBwcm9ncmVzc0NiKHByb2dyZXNzMTAwKSwgMyk7XG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiByZXNvbHZlKFtdKSwgNCk7XG5cbiAgICAgICAgICBqZXN0LmFkdmFuY2VUaW1lcnNCeVRpbWUoNCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGplc3Quc3B5T24oUzNVcGxvYWRlci5wcm90b3R5cGUsICdvbicpLm1vY2tJbXBsZW1lbnRhdGlvbigoZXYsIGNiKSA9PiB7XG4gICAgICAgIHByb2dyZXNzQ2IgPSBjYjtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcHJvZ3Jlc3NNb2NrID0gamVzdC5mbigpO1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFVwbG9hZCh7XG4gICAgICAgIHByb2dyZXNzSW50ZXJ2YWw6IDEsXG4gICAgICAgIG9uUHJvZ3Jlc3M6IHByb2dyZXNzTW9jayxcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCB1Lm11bHRpdXBsb2FkKFt0ZXN0QnVmZmVyXSk7XG5cbiAgICAgIGV4cGVjdChwcm9ncmVzc01vY2spLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHByb2dyZXNzMSk7XG4gICAgICBleHBlY3QocHJvZ3Jlc3NNb2NrKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChwcm9ncmVzczUwKTtcbiAgICAgIGV4cGVjdChwcm9ncmVzc01vY2spLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHByb2dyZXNzMTAwKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc3RheSBhdCB0aGUgc2FtZSBwcm9ncmVzcyB3aGVuIHVwbG9hZGVyIGdvZXMgYmFjayB3aXRoIGZpbGUgcHJvZ3Jlc3MnLCBhc3luYyAoKSA9PiB7XG4gICAgICBsZXQgcHJvZ3Jlc3NDYjtcblxuICAgICAgbW9ja0V4ZWN1dGUubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gcHJvZ3Jlc3NDYihwcm9ncmVzczUwKSwgMSk7XG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiBwcm9ncmVzc0NiKHByb2dyZXNzMSksIDIpO1xuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gcHJvZ3Jlc3NDYihwcm9ncmVzczEwMCksIDMpO1xuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gcmVzb2x2ZShbXSksIDQpO1xuXG4gICAgICAgICAgamVzdC5hZHZhbmNlVGltZXJzQnlUaW1lKDQpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBqZXN0LnNweU9uKFMzVXBsb2FkZXIucHJvdG90eXBlLCAnb24nKS5tb2NrSW1wbGVtZW50YXRpb24oKGV2LCBjYikgPT4ge1xuICAgICAgICBwcm9ncmVzc0NiID0gY2I7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHByb2dyZXNzTW9jayA9IGplc3QuZm4oKTtcblxuICAgICAgY29uc3QgdSA9IG5ldyBVcGxvYWQoe1xuICAgICAgICBwcm9ncmVzc0ludGVydmFsOiAxLFxuICAgICAgICBvblByb2dyZXNzOiBwcm9ncmVzc01vY2ssXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgdS5tdWx0aXVwbG9hZChbdGVzdEJ1ZmZlcl0pO1xuXG4gICAgICBleHBlY3QocHJvZ3Jlc3NNb2NrKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChwcm9ncmVzczUwKTtcbiAgICAgIGV4cGVjdChwcm9ncmVzc01vY2spLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHByb2dyZXNzNTApO1xuICAgICAgZXhwZWN0KHByb2dyZXNzTW9jaykudG9IYXZlQmVlbkNhbGxlZFdpdGgocHJvZ3Jlc3MxMDApO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19