filestack-js
Version:
Official JavaScript library for Filestack
366 lines (292 loc) • 10.4 kB
text/typescript
/*
* 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 { Upload } from './upload';
import { FileState } from './file';
import { S3Uploader } from './uploaders/s3';
import { config } from './../../../config';
import { StoreUploadOptions } from './types';
import { UploadMode } from './uploaders/abstract';
const testBuffer = Buffer.from('test test test');
const customNameMocked = jest.fn();
const mockedFsFile = {};
Object.defineProperty(mockedFsFile, 'customName', {
set: customNameMocked,
});
jest.useFakeTimers();
jest.mock('./uploaders/s3');
jest.mock('./file_tools', () => ({
getFile: jest.fn().mockImplementation(() => mockedFsFile),
}));
const mockedFileResponse = {
status: 'stored',
};
const sessionURls = config.urls;
const defaultSession = {
apikey: 'test',
policy: 'p',
signature: 's',
urls: sessionURls,
};
const mockExecute = jest.fn();
describe('Api/Upload/upload', () => {
beforeAll(() => {
jest.spyOn(S3Uploader.prototype, 'execute').mockImplementation(mockExecute);
});
describe('Settings', () => {
it('should handle constructor options', () => {
const 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', () => {
// @ts-ignore
expect(() => new Upload({ intelligent1: true })).toThrowError('Invalid upload params');
});
it('should accept sanitizer settings', () => {
expect(() => new Upload({}, {
// @ts-ignore
sanitizer: false,
})).not.toThrowError('Invalid upload params');
expect(() => new Upload({}, {
// @ts-ignore
sanitizer: {
exclude: ['1'],
replacement: '-',
},
})).not.toThrowError('Invalid upload params');
});
it('should throw error on wrong store options', () => {
// @ts-ignore
expect(() => new Upload({ intelligent: true }, { test: 123 })).toThrowError('Invalid store upload params');
});
it('should set intelligent upload mode', () => {
const u = new Upload({ intelligent: true });
expect(S3Uploader.prototype.setUploadMode).toHaveBeenCalledWith(UploadMode.INTELLIGENT);
});
it('should set respect disableIntegrityCheck param', () => {
const u = new Upload({ disableIntegrityCheck: true });
expect(S3Uploader.prototype.setIntegrityCheck).toHaveBeenCalledWith(false);
});
it('should fallback upload mode', () => {
const u = new Upload({ intelligent: 'fallback' });
expect(S3Uploader.prototype.setUploadMode).toHaveBeenCalledWith(UploadMode.FALLBACK);
});
it('should set upload tasks to uploader', () => {
const tags = { test: '123' };
const u = new Upload({ tags: tags });
expect(S3Uploader.prototype.setUploadTags).toHaveBeenCalledWith(tags);
});
it('should pass store options to uploader class', () => {
const storeOptions: StoreUploadOptions = {
location: 's3',
};
const u = new Upload({}, storeOptions);
expect(S3Uploader.prototype.constructor).toHaveBeenCalledWith(storeOptions, undefined);
});
it('should respect concurrency param in upload options', () => {
const uploadOptions = {
concurrency: 4,
};
const u = new Upload(uploadOptions);
expect(S3Uploader.prototype.constructor).toHaveBeenCalledWith({}, 4);
});
it('should set correct security to uploader', () => {
const security = {
policy: 'p',
signature: 's',
};
const u = new Upload();
u.setSecurity(security);
expect(S3Uploader.prototype.setSecurity).toHaveBeenCalledWith(security);
});
it('should pass session variable to uploader', () => {
const 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', async () => {
mockExecute.mockReturnValue(Promise.resolve([mockedFileResponse]));
const filenameFn = () => 'test';
const u = new Upload(
{},
{
filename: filenameFn,
}
);
await u.upload(testBuffer);
expect(customNameMocked).toHaveBeenCalledWith(filenameFn);
});
it('should assign methods to user provided token', () => {
let token = {};
const 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', () => {
let token = {};
const 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', () => {
const token = '123123';
const u = new Upload();
expect(() => {
u.setToken(token);
}).toThrowError();
});
});
describe('Upload', () => {
beforeEach(() => {
mockExecute.mockReturnValue(Promise.resolve([mockedFileResponse, mockedFileResponse]));
});
it('should execute normal upload without errors and return single file response', async () => {
const u = new Upload();
const res = await u.upload(testBuffer);
expect(res).toEqual(mockedFileResponse);
});
it('should execute normal upload with errors and return rejected promise', () => {
const u = new Upload();
mockExecute.mockReturnValue(
Promise.resolve([
{
status: FileState.FAILED,
},
])
);
return expect(u.upload(testBuffer)).rejects.toEqual({
status: FileState.FAILED,
});
});
it('should execute multiupload without errors and return single file response', async () => {
const u = new Upload();
const res = await u.multiupload([testBuffer, testBuffer]);
expect(res).toEqual([mockedFileResponse, mockedFileResponse]);
});
});
describe('Progress', () => {
const progress1 = {
totalBytes: 1,
totalPercent: 1,
files: [
{
totalBytes: 1,
totalPercent: 1,
},
],
};
const progress50 = {
totalBytes: 5,
totalPercent: 50,
files: [
{
totalBytes: 50,
totalPercent: 50,
},
],
};
const progress100 = {
totalBytes: 100,
totalPercent: 100,
files: [
{
totalBytes: 100,
totalPercent: 100,
},
],
};
it('should handle correct progress event', async () => {
jest.spyOn(S3Uploader.prototype, 'on').mockImplementation((ev, cb) => {
cb(progress1);
cb(progress100);
return this;
});
const progressMock = jest.fn();
const u = new Upload({
onProgress: progressMock,
});
await u.upload(testBuffer);
expect(progressMock).toHaveBeenCalledWith(progress100);
expect(progressMock).toHaveBeenCalledTimes(1);
});
it('should call progress event on given interval', async () => {
let progressCb;
mockExecute.mockImplementation(() => {
return new Promise(resolve => {
setTimeout(() => progressCb(progress1), 1);
setTimeout(() => progressCb(progress50), 2);
setTimeout(() => progressCb(progress100), 3);
setTimeout(() => resolve([]), 4);
jest.advanceTimersByTime(4);
});
});
jest.spyOn(S3Uploader.prototype, 'on').mockImplementation((ev, cb) => {
progressCb = cb;
return this;
});
const progressMock = jest.fn();
const u = new Upload({
progressInterval: 1,
onProgress: progressMock,
});
await u.multiupload([testBuffer]);
expect(progressMock).toHaveBeenCalledWith(progress1);
expect(progressMock).toHaveBeenCalledWith(progress50);
expect(progressMock).toHaveBeenCalledWith(progress100);
});
it('should stay at the same progress when uploader goes back with file progress', async () => {
let progressCb;
mockExecute.mockImplementation(() => {
return new Promise(resolve => {
setTimeout(() => progressCb(progress50), 1);
setTimeout(() => progressCb(progress1), 2);
setTimeout(() => progressCb(progress100), 3);
setTimeout(() => resolve([]), 4);
jest.advanceTimersByTime(4);
});
});
jest.spyOn(S3Uploader.prototype, 'on').mockImplementation((ev, cb) => {
progressCb = cb;
return this;
});
const progressMock = jest.fn();
const u = new Upload({
progressInterval: 1,
onProgress: progressMock,
});
await u.multiupload([testBuffer]);
expect(progressMock).toHaveBeenCalledWith(progress50);
expect(progressMock).toHaveBeenCalledWith(progress50);
expect(progressMock).toHaveBeenCalledWith(progress100);
});
});
});