UNPKG

filestack-js

Version:

Official JavaScript library for Filestack

650 lines (533 loc) 18.1 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 { 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(); }); }); }); });