import { describe , it , beforeEach , afterEach } from 'tman' ; import { expect } from 'chai' ; import * as sinon from 'sinon' ; import * as moment from 'moment' ; import * as URL from 'url' ; import { createSdkWithoutRDB , context , SDK , UserMe } from '..' ; const mockRequire = require ( 'mock-require' ) ; const atob = require ( 'atob' ) ; context . atob = context . atob || atob ; describe ( 'SocketClient' , ( ) => { const userMe = { tcmToken : 'mock-tcm-token' } as UserMe ; let sdk ; let sandbox ; let fetchSpy ; beforeEach ( ( ) => { sandbox = sinon . createSandbox ( ) ; mockRequire ( 'xmlhttprequest-ssl' , class XMLHttpRequest { open = ( fetchSpy = sandbox . spy ( ) ) ; send = sandbox . spy ( ) ; } ) ; sdk = createSdkWithoutRDB ( ) ; const Consumer = require ( 'snapper-consumer' ) ; sdk . socketClient . initClient ( new Consumer ( ) , userMe ) ; sandbox . stub ( context , 'atob' ) . value ( ( ) => { return JSON . stringify ( { exp : moment ( ) . add ( 1 , 'y' ) . valueOf ( ) } ) ; } ) ; } ) ; afterEach ( ( ) => { sandbox . restore ( ) ; mockRequire . stopAll ( ) ; } ) ; it ( 'should connect to target URL (HTTP)' , async ( ) => { const socketUrl = 'http://localhost:1111' ; const url = `${ socketUrl }/websocket/?token=${ userMe . tcmToken }` ; sdk . socketClient . setSocketUrl ( socketUrl ) ; await sdk . socketClient . connect ( ) ; expect ( fetchSpy . calledWith ( 'GET' , sinon . match ( url ) ) ) . to . be . true ; } ) ; it ( 'should connect to target URL (WS)' , async ( ) => { const socketUrl = 'ws://localhost:1111' ; const url = `${ socketUrl }/websocket/?token=${ userMe . tcmToken }` ; sdk . socketClient . setSocketUrl ( socketUrl ) ; await sdk . socketClient . connect ( ) ; expect ( fetchSpy . calledWith ( 'GET' , sinon . match ( ( pollingUri ) => matchPollingUri ( pollingUri , url ) ) ) ) . to . be . true ; } ) ; it ( 'should allow SocketURL (HTTP) including url' , async ( ) => { const socketUrl = 'http://localhost:1111/messaging' ; const url = `${ socketUrl }/websocket/?token=${ userMe . tcmToken }` ; sdk . socketClient . setSocketUrl ( socketUrl ) ; await sdk . socketClient . connect ( ) ; expect ( fetchSpy . calledWith ( 'GET' , sinon . match ( url ) ) ) . to . be . true ; } ) ; it ( 'should allow SocketURL (WS) including url' , async ( ) => { const socketUrl = 'ws://localhost:1111/messaging' ; const url = `${ socketUrl }/websocket/?token=${ userMe . tcmToken }` ; sdk . socketClient . setSocketUrl ( socketUrl ) ; await sdk . socketClient . connect ( ) ; expect ( fetchSpy . calledWith ( 'GET' , sinon . match ( ( pollingUri ) => matchPollingUri ( pollingUri , url ) ) ) ) . to . be . true ; } ) ; it ( 'should not append `/websocket` postfix if the SocketURL already has it' , async ( ) => { const socketUrl = 'ws://localhost:1111/messaging/websocket' ; const url = `ws://localhost:1111/messaging/websocket/?token=${ userMe . tcmToken }` ; sdk . socketClient . setSocketUrl ( socketUrl ) ; await sdk . socketClient . connect ( ) ; expect ( fetchSpy . calledWith ( 'GET' , sinon . match ( ( pollingUri ) => matchPollingUri ( pollingUri , url ) ) ) ) . to . be . true ; } ) ; } ) ; const matchPollingUri = ( actual , expected ) => { const actualUri = toPollingUri ( actual ) ; const expectedUri = toPollingUri ( expected ) ; return actualUri . includes ( expectedUri ) ; } ; const toPollingUri = ( url ) => { const urlObj = URL . parse ( url ) ; const schema = ( urlObj . protocol && PollingUriSchemaMap [ urlObj . protocol ] ) || urlObj . protocol ; return URL . format ( { ... urlObj , protocol : schema } ) ; } ; const PollingUriSchemaMap = { 'ws:' : 'http:' , 'wss:' : 'https:' } ;