filestack-js
Version:
Official JavaScript library for Filestack
650 lines (533 loc) • 18.1 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 { config } from './../../config';
import { CloudClient, PICKER_KEY } from './cloud';
import * as utils from './../utils/index.node';
import nock from 'nock';
import { Store, STORE_TYPE } from '../utils/store';
const testApiKey = 'API_KEY';
const testTokSession = 'TOK_SESSION';
const testTokArchiveId = 'ARCHIVE_ID';
const testCloudToken = 'testCloudToken';
const testSecurity = {
policy: 'examplePolicy',
signature: 'exampleSignature',
};
const sessionURls = config.urls;
const testSession = {
apikey: testApiKey,
urls: sessionURls,
};
let scope = nock(sessionURls.cloudApiUrl);
scope.defaultReplyHeaders({
'access-control-allow-origin': function (req) { return req.getHeader('origin')?.toString(); },
'access-control-allow-methods': function (req) { return req.getHeader('access-control-request-method')?.toString(); },
'access-control-allow-headers': function (req) { return req.getHeader('access-control-request-headers')?.toString(); },
'content-type': 'application/json',
});
const mockTokInit = jest
.fn()
.mockName('tokInit')
.mockReturnValue('init');
const mockTokStart = jest
.fn()
.mockName('tokStart')
.mockReturnValue('start');
const mockTokStop = jest
.fn()
.mockName('tokStop')
.mockReturnValue('stop');
const mockMetadata = jest
.fn()
.mockName('metadata')
.mockReturnValue('metadata');
const mockList = jest
.fn()
.mockName('list')
.mockImplementation(data => {
if (data && data.clouds.token) {
return { token: testCloudToken };
}
return data;
});
const mockLogout = jest
.fn()
.mockName('logout')
.mockImplementation((url, params) => {
if (params.clouds && params.clouds.token) {
return { token: testCloudToken };
}
return params;
});
const mockStore = jest
.fn()
.mockName('store')
.mockImplementation(params => {
if (params && params.clouds && params.clouds.token) {
return JSON.stringify({ token: testCloudToken });
}
return JSON.stringify(params);
});
describe('cloud', () => {
beforeEach(() => {
scope
.persist()
.options(/.*/)
.reply(204, '', {
'access-control-allow-headers': 'filestack-source,filestack-trace-id,filestack-trace-span',
'access-control-allow-methods': '*',
'access-control-allow-origin': '*',
});
scope.post('/auth/logout').reply(200, mockLogout);
scope.post('/folder/list').reply(200, (_, data) => mockList(data));
scope.post('/store/').reply(200, (_, data) => mockStore(data));
scope.post('/metadata').reply(200, mockMetadata);
scope.post(/\/recording\/(audio|video)\/init/).reply(200, mockTokInit);
scope.post(/\/recording\/(audio|video)\/start/).reply(200, mockTokStart);
scope.post(/\/recording\/(audio|video)\/stop/).reply(200, mockTokStop);
});
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
localStorage.clear();
});
describe('cancelToken', () => {
const testDomain = 'http://delay.filestack.test';
let scopeD;
beforeEach(() => {
scopeD = nock(testDomain);
scopeD
.post('/store/')
.delay(4000)
.reply(200);
scopeD
.post('/folder/list')
.delay(4000)
.reply(200);
scopeD
.persist()
.options(/.*/)
.reply(204, '', {
'access-control-allow-headers': 'filestack-source,filestack-trace-id,filestack-trace-span',
'access-control-allow-methods': '*',
'access-control-allow-origin': '*',
});
});
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
localStorage.clear();
});
it('Should cancel store request', done => {
const sessionClone = JSON.parse(JSON.stringify(testSession));
sessionClone.urls.cloudApiUrl = testDomain;
let token = {};
new CloudClient(sessionClone)
.store('google', 'test', { filename: '1', location: 'gcs' }, {}, token)
.then(() => {
done('Request not canceled');
})
.catch(err => {
expect(err).toEqual(expect.any(Error));
done();
});
setTimeout(() => {
// @ts-ignore
token.cancel();
}, 500);
});
it('Should cancel list request', done => {
const sessionClone = JSON.parse(JSON.stringify(testSession));
sessionClone.urls.cloudApiUrl = testDomain;
let token = {};
new CloudClient(sessionClone)
.list('google', token)
.then(() => {
done('Request not canceled');
})
.catch(err => {
expect(err).toEqual(expect.any(Error));
done();
});
setTimeout(() => {
// @ts-ignore
token.cancel();
}, 500);
});
});
describe('facebook inapp browser', () => {
it('should set token to sessionStore when inapp browser is detected', async () => {
jest.spyOn(utils, 'isFacebook').mockReturnValue(true);
const client = new CloudClient(Object.assign({}, testSession, {
prefetch: {
settings: {
inapp_browser: true,
},
pickerOptions: {},
},
}));
const token = 'test';
client.token = token;
const store = new Store();
expect(store.getItem(PICKER_KEY, STORE_TYPE.SESSION)).toEqual(token);
store.setItem(PICKER_KEY, undefined, STORE_TYPE.SESSION);
});
it('should get token from sessionStore when inapp browser is detected', async () => {
jest.spyOn(utils, 'isFacebook').mockReturnValue(true);
const client = new CloudClient(Object.assign({}, testSession, {
prefetch: {
settings: {
inapp_browser: true,
},
pickerOptions: {},
},
}));
const store = new Store();
const token = 'test';
store.setItem(PICKER_KEY, token, STORE_TYPE.SESSION);
expect(client.token).toEqual(token);
store.setItem(PICKER_KEY, undefined, STORE_TYPE.SESSION);
});
it('should send appurl in list action', async () => {
const clouds = { test: true };
const client = new CloudClient(Object.assign({}, testSession, {
prefetch: {
settings: {
inapp_browser: true,
},
pickerOptions: {},
},
}));
const res = await client.list({ ...clouds });
expect(res).toEqual({
apikey: testApiKey,
flow: 'web',
appurl: 'http://localhost/?fs-tab=init',
clouds,
token: null,
});
});
it('should send pass mimetypes to backend as string', async () => {
const clouds = { test: true };
const client = new CloudClient(Object.assign({}, testSession, {
prefetch: {
settings: {
inapp_browser: true,
},
pickerOptions: {},
},
}));
const res = await client.list({ ...clouds }, {}, 'image/*');
expect(res).toEqual({
apikey: testApiKey,
flow: 'web',
appurl: 'http://localhost/?fs-tab=init',
clouds,
token: null,
accept: ['image/*'],
});
});
it('should send pass mimetypes to backend as array', async () => {
const clouds = { test: true };
const client = new CloudClient(Object.assign({}, testSession, {
prefetch: {
settings: {
inapp_browser: true,
},
pickerOptions: {},
},
}));
const res = await client.list({ ...clouds }, {}, ['image/*']);
expect(res).toEqual({
apikey: testApiKey,
flow: 'web',
appurl: 'http://localhost/?fs-tab=init',
clouds,
token: null,
accept: ['image/*'],
});
});
});
it('should not send app url if urlsearch params is undefined', async () => {
const clouds = { test: true };
const before = window.URLSearchParams;
window.URLSearchParams = undefined;
const client = new CloudClient(Object.assign({}, testSession, {
prefetch: {
settings: {
inapp_browser: true,
},
pickerOptions: {},
},
}));
const res = await client.list({ ...clouds });
expect(res).toEqual({
apikey: testApiKey,
flow: 'web',
clouds,
token: null,
});
window.URLSearchParams = before;
});
describe('list', () => {
it('should make correct list request', async () => {
const clouds = { test: true };
const res = await new CloudClient(testSession).list({ ...clouds });
expect(res).toEqual({
apikey: testApiKey,
flow: 'web',
clouds,
});
});
it('should make correct list request with session cache', async () => {
const clouds = { test: true };
localStorage.setItem(PICKER_KEY, testCloudToken);
const res = await new CloudClient(testSession, {
sessionCache: true,
}).list({ ...clouds });
expect(res).toEqual({
apikey: testApiKey,
flow: 'web',
token: testCloudToken,
clouds,
});
});
it('should set token on api token response', async () => {
const clouds = { token: true };
const res = await new CloudClient(testSession).list({ ...clouds });
expect(res).toEqual({ token: testCloudToken });
});
it('should cache session token to local storage', async () => {
const clouds = { token: true };
const res = await new CloudClient(testSession, { sessionCache: true }).list({ ...clouds });
expect(localStorage.setItem).toHaveBeenCalledWith(PICKER_KEY, testCloudToken);
expect(res).toEqual({ token: testCloudToken });
});
it('should make correct list request with security', async () => {
const clouds = { test: true };
const res = await new CloudClient({
...testSession,
...testSecurity,
}).list({ ...clouds });
expect(res).toEqual({
apikey: testApiKey,
flow: 'web',
clouds,
...testSecurity,
});
});
});
describe('store', () => {
it('should make correct basic request', async () => {
const res = await new CloudClient(testSession).store('google', 'test', { filename: '1' });
expect(res).toEqual({
apikey: testApiKey,
flow: 'web',
clouds: {
google: {
path: 'test',
store: {
filename: '1',
location: 's3',
},
},
},
});
});
it('should respect store location param', async () => {
const res = await new CloudClient(testSession).store('google', 'test', { filename: '1', location: 'gcs' });
expect(res).toEqual({
apikey: testApiKey,
flow: 'web',
clouds: {
google: {
path: 'test',
store: {
filename: '1',
location: 'gcs',
},
},
},
});
});
it('should respect store upload tags', async () => {
const uploadTags = { testTag: 'testTag' };
const res = await new CloudClient(testSession).store('google', 'test', {}, null, null, uploadTags);
expect(res).toEqual({
apikey: testApiKey,
flow: 'web',
upload_tags: uploadTags,
clouds: {
google: {
path: 'test',
store: {
location: 's3',
},
},
},
});
});
it('should make correct basic with security', async () => {
const res = await new CloudClient({
...testSession,
...testSecurity,
}).store('token', 'test', { filename: '1' });
const excepted = {
...testSecurity,
apikey: testApiKey,
flow: 'web',
clouds: {
token: {
path: 'test',
store: {
filename: '1',
location: 's3',
},
},
},
};
expect(mockStore).toHaveBeenCalledWith(excepted);
expect(res).toEqual(testCloudToken);
});
it('should handle custom source', async () => {
const customSource = {
customSourcePath: 'cs_path',
customSourceContainer: 'cs_container',
};
const res = await new CloudClient(testSession).store('customsource', 'test', { filename: '1' }, customSource);
expect(res).toEqual({
apikey: testApiKey,
flow: 'web',
clouds: {
customsource: {
...customSource,
path: 'test',
store: {
filename: '1',
location: 's3',
},
},
},
});
});
});
describe('logout', () => {
it('should make correct request to logout', async () => {
expect(await new CloudClient(testSession).logout()).toEqual({ apikey: 'API_KEY', flow: 'web' });
});
it('should make correct request to logout with provided cloud', async () => {
expect(await new CloudClient(testSession).logout('google')).toEqual({ apikey: 'API_KEY', flow: 'web', clouds: { google: {} } });
});
it('should make correct request to logout and return correct response when cloud name is returned', async () => {
expect(await new CloudClient(testSession).logout('token')).toEqual('testCloudToken');
});
it('should make correct request to logout and clean session cache ', async () => {
localStorage.setItem(PICKER_KEY, testCloudToken);
const res = await new CloudClient(testSession, { sessionCache: true }).logout();
expect(localStorage.removeItem).toHaveBeenCalledWith(PICKER_KEY);
expect(res).toEqual({ apikey: 'API_KEY', flow: 'web', token: testCloudToken });
});
});
describe('metadata', () => {
it('should make correct request', async () => {
const testUrl = 'http://test.com';
const res = await new CloudClient(testSession).metadata(testUrl);
expect(mockMetadata).toHaveBeenCalledWith(expect.any(String), {
apikey: testApiKey,
url: testUrl,
});
expect(res).toEqual('metadata');
});
it('should make correct request with security', async () => {
const testUrl = 'http://test.com';
const res = await new CloudClient({
...testSession,
...testSecurity,
}).metadata(testUrl);
expect(mockMetadata).toHaveBeenCalledWith(expect.any(String), {
apikey: testApiKey,
url: testUrl,
...testSecurity,
});
expect(res).toEqual('metadata');
});
});
describe('OpenTok', () => {
describe('tokInit', () => {
it('should make correct request to api (audio)', async () => {
const res = await new CloudClient(testSession).tokInit('audio');
expect(mockTokInit).toHaveBeenCalledWith(expect.any(String), '');
expect(res).toEqual('init');
});
it('should make correct request to api (video)', async () => {
const res = await new CloudClient(testSession).tokInit('audio');
expect(mockTokInit).toHaveBeenCalledWith(expect.any(String), '');
expect(res).toEqual('init');
});
it('should throw on wrong type', async () => {
expect(() => {
new CloudClient(testSession)
.tokInit('videoa')
.then(() => {
console.log('init');
})
.catch(() => {
console.log('err');
});
}).toThrowError();
});
});
describe('tokStart', () => {
it('should make correct request to api (audio)', async () => {
const res = await new CloudClient(testSession).tokStart('audio', 'key', testTokSession);
expect(mockTokStart).toHaveBeenCalledWith(expect.any(String), { apikey: 'key', session_id: testTokSession });
expect(res).toEqual('start');
});
it('should make correct request to api (video)', async () => {
const res = await new CloudClient(testSession).tokStart('video', 'key', testTokSession);
expect(mockTokStart).toHaveBeenCalledWith(expect.any(String), { apikey: 'key', session_id: testTokSession });
expect(res).toEqual('start');
});
it('should throw on wrong type', () => {
expect(() => new CloudClient(testSession).tokStart('videoa', 'key', testTokSession)).toThrowError();
});
});
describe('tokStop', () => {
it('should make correct request to api (audio)', async () => {
const res = await new CloudClient(testSession).tokStop('audio', 'key', testTokSession, testTokArchiveId);
expect(mockTokStop).toHaveBeenCalledWith(expect.any(String), {
apikey: 'key',
session_id: testTokSession,
archive_id: testTokArchiveId,
});
expect(res).toEqual('stop');
});
it('should make correct request to api (video)', async () => {
const res = await new CloudClient(testSession).tokStop('video', 'key', testTokSession, testTokArchiveId);
expect(mockTokStop).toHaveBeenCalledWith(expect.any(String), {
apikey: 'key',
session_id: testTokSession,
archive_id: testTokArchiveId,
});
expect(res).toEqual('stop');
});
it('should throw on wrong type', () => {
expect(() => new CloudClient(testSession).tokStop('videoa', 'key', testTokSession, testTokArchiveId)).toThrowError();
});
});
});
});