UNPKG

icomoon-build

Version:
442 lines (340 loc) 11.1 kB
exports.init = phantomXHRInit; exports.fake = fake; exports.requests = getAllRequests; var page; function phantomXHRInit(initPage, options){ var inject = false; options = options || {}; if(initPage.injectJs){ initPage.evaluate(function(){ // Shim these constructors to make progress events work in PhantomJS window.ProgressEvent = function(){}; window.CustomEvent = function(){}; }); inject = initPage.injectJs(options.libraryRoot ? (options.libraryRoot + 'sinon.js') : './node_modules/phantomxhr/sinon.js'); initPage.evaluate(function(){ // A naive implementation for simulating upload events function FakeEvent(type, bubbles, cancelable, target) { this.initEvent(type, bubbles, cancelable, target); }; FakeEvent.prototype = { initEvent: function(type, event, cancelable, target) { var key; this.type = type; this.bubbles = event; this.lengthComputable = true; this.isTrusted = true; this.cancelable = cancelable; this.target = target; this.loaded = 0; this.total = 0; for ( key in event ){ this[key] = event[key]; } }, stopPropagation: function () {}, stopImmediatePropagation: function () {}, preventDefault: function () { this.defaultPrevented = true; } }; window.ProgressEvent = FakeEvent; window.CustomEvent = FakeEvent; }); } if(inject){ page = initPage; setup(); } else { console.log("[PhantomXHR] Can't find sinon.js"); } } function setup(){ page.evaluate(function () { if (!window._ajaxmock_) { window._ajaxmock_ = { matches: [], requests: {}, call: {}, fake: function (match) { function S4() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); } function makeGuid() { return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()); } var urlIsString = match.url.indexOf('REGEXP') === -1; var guid = makeGuid(); match.guid = guid; match.url = match.url.replace('REGEXP', ''); console.log('[PhantomXHR] Match added [' + (match.method || 'All REST verbs') + "] : " + match.url + "'"); match.requests = []; match.responses = []; match.respondMethods = []; window._ajaxmock_.call[guid] = match; window._ajaxmock_.matches.push(function (method, url) { if (!url) { return false; } var urlMatch = urlIsString ? url.indexOf(match.url) !== -1 : new RegExp(match.url).test(url); var methodMatch = (typeof match.method === 'undefined') ? true : match.method.toLowerCase() === method.toLowerCase(); if (urlMatch && methodMatch) { return match; } else { return false; } }); return guid; }, init: function () { var _xhr = window.sinon.useFakeXMLHttpRequest(); _xhr.upload = document.createElement('div'); _xhr.onCreate = function (request) { setTimeout(function () { var anyMatches = false; var requests = window._ajaxmock_.requests; if (!request.url) { console.log('[PhantomXHR] XHR has been initialised but not opened.'); return; } // this shouldn't happen, but sometimes does // store the request for later matching if (requests[request.method.toLowerCase() + request.url]) { requests[request.method.toLowerCase() + request.url].count++; } else { requests[request.method.toLowerCase() + request.url] = { data: request, count: 1 }; } window._ajaxmock_.matches.reverse().forEach(function (func) { anyMatches = anyMatches || func(request.method, request.url); }); if (anyMatches) { respond(request, anyMatches); } else { console.log('[PhantomXHR] did not respond to ' + request.method + ' ' + request.url); } }, 100); }; } }; window._ajaxmock_.init(); } function respond(request, response) { if(!window._ajaxmock_){ console.log('[PhantomXHR] could not respond, window._ajaxmock_ does not exist.'); return; } var call = window._ajaxmock_.call; var callForThisMatch; var responseForThisMatch; var status; var body; console.log('[PhantomXHR] recieved request for ' + request.method + ": " + request.url + "'"); callForThisMatch = call[response.guid]; callForThisMatch.requests.push(request); responseForThisMatch = callForThisMatch.responses[callForThisMatch.requests.length]; if (responseForThisMatch) { status = responseForThisMatch.status; body = responseForThisMatch.responseBody; console.log('[PhantomXHR] with status: ' + responseForThisMatch.status); } console.log('[PhantomXHR] with status: ' + response.status); if(response.holdResponse){ callForThisMatch.respondMethods.push(function(responseOverride){ responseOverride = responseOverride || response; console.log('[PhantomXHR] Responding to postponed ' + request.method + ": " + request.url + "'"); request.respond( status || responseOverride.status || 200, responseOverride.headers || { "Content-Type": "application/json" }, body || responseOverride.responseBody || '' ); }); } else { console.log('[PhantomXHR] Responding to ' + request.method + ": " + request.url + "'"); console.log('[PhantomXHR] status ', status , response.status , 200); request.respond( status || response.status || 200, response.headers || { "Content-Type": "application/json" }, body || response.responseBody || '' ); } } }); } function fake(options) { var url = !! options.url.source ? 'REGEXP' + options.url.source : options.url; if(typeof(options.responseBody) === "object"){ options.responseBody = JSON.stringify(options.responseBody); } var guid = page.evaluate(function (url, method, responseBody, status, headers, holdResponse) { if (window._ajaxmock_ && url) { if (responseBody && headers && headers["Content-Type"] && headers["Content-Type"] === "application/json") { try { JSON.parse(responseBody); } catch (e) { return 'JSON'; } } return window._ajaxmock_.fake({ url: url, method: method, responseBody: responseBody, status: status, headers: headers, holdResponse: holdResponse }); } }, url, options.method, options.responseBody, options.status, options.headers, !!options.holdResponse); if (guid === 'JSON') { console.log('[PhantomXHR] JSON was invalid : ' + options.method + ' : ' + url); } return { count: function () { var c = page.evaluate(function (guid) { if( !(window._ajaxmock_ && window._ajaxmock_.call[guid] )){ return; } return window._ajaxmock_.call[guid].requests.length; }, guid); if(typeof c === 'undefined'){ console.log('[PhantomXHR] Could not get count'); } return c; }, nthRequest: function (index) { var r = page.evaluate(function (guid, index) { if( !(window._ajaxmock_ && window._ajaxmock_.call[guid] )){ return; } var request = window._ajaxmock_.call[guid].requests[index - 1]; return request.requestBody; }, guid, index); if(typeof r === 'undefined'){ console.log('[PhantomXHR] Could not get request'); } return r; }, nthRequestOrNull: function (index) { var r = page.evaluate(function (guid, index) { if( !(window._ajaxmock_ && window._ajaxmock_.call[guid] )){ return; } var request = window._ajaxmock_.call[guid].requests[index - 1]; if (!request) { return null; } return request; }, guid, index); if(typeof r === 'undefined'){ console.log('[PhantomXHR] Could not get request'); } return r; }, last: function () { var last = page.evaluate(function (guid) { return window._ajaxmock_.call[guid].requests.length; }, guid); return this.nthRequest(last); }, first: function () { return this.nthRequest(1); }, firstOrNull: function () { return this.nthRequestOrNull(1); }, nthResponse: function (num, response) { var r = page.evaluate(function (guid, num, response) { if (typeof(response.responseBody) === "object") { response.responseBody = JSON.stringify(response.responseBody); } if( !(window._ajaxmock_ && window._ajaxmock_.call[guid] )){ return; } window._ajaxmock_.call[guid].responses[num-1] = response; return true; }, guid, num, response ); if(typeof r === 'undefined'){ console.log('[PhantomXHR] Could not set response'); } return this; }, nthProgress: function(nth, event){ function isNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); } if( isNumber(event.loaded) && isNumber(event.total) ){ page.evaluate(function (guid, nth, event) { var mock = window._ajaxmock_; var req; if( !(mock && mock.call[guid]) ){ return; } req = mock.call[guid].requests[nth-1]; if(req){ req.uploadProgress(event); } }, guid, nth, event); } else { console.log('[PhantomXHR] Could not set progress'); } }, nthRespond: function(nth, response){ // if you don't want to respond immediately page.evaluate(function (guid, nth, response) { var placeholder = 'placeholder'; var si; var item; function processResponse(){ var res; var method; var item = window._ajaxmock_.call[guid]; var queue = item.queuedResponses; if(queue && item.respondMethods.length){ res = queue[nth-1]; method = item.respondMethods[nth-1]; if(method){ method(res === placeholder ? void 0 : res); } if(si) { clearInterval(si); } return true; } return false; } response = response || placeholder; if( !(window._ajaxmock_ && window._ajaxmock_.call[guid] )){ return; } item = window._ajaxmock_.call[guid]; if(!item.queuedResponses) { item.queuedResponses = []; } item.queuedResponses = []; item.queuedResponses.push(response); if(!processResponse()){ si = setInterval(processResponse,50); } }, guid, nth, response); }, respond: function(response){ return this.nthRespond(1, response); }, progress: function(event){ return this.nthProgress(1, event); }, uri: options.url, method: options.method }; } function getAllRequests() { var requests = page.evaluate(function () { var requests = {}; if (window._ajaxmock_) { requests = window._ajaxmock_.requests; } return requests; }); return requests; }