mirror of
https://github.com/silkimen/cordova-plugin-advanced-http.git
synced 2026-04-24 00:00:03 +08:00
- WIP: implement data pre-processor for #101
- implement checks for #101 - add some specs
This commit is contained in:
+81
-16
@@ -2,6 +2,9 @@ const chai = require('chai');
|
||||
const mock = require('mock-require');
|
||||
const should = chai.should();
|
||||
|
||||
const ConsoleMock = require('./mocks/Console.mock');
|
||||
const FormDataMock = require('./mocks/FormData.mock');
|
||||
|
||||
describe('Advanced HTTP public interface', function () {
|
||||
const messages = require('../www/messages');
|
||||
|
||||
@@ -17,7 +20,7 @@ describe('Advanced HTTP public interface', function () {
|
||||
const errorCodes = require('../www/error-codes');
|
||||
const WebStorageCookieStore = require('../www/local-storage-store')(ToughCookie, lodash);
|
||||
const cookieHandler = require('../www/cookie-handler')(null, ToughCookie, WebStorageCookieStore);
|
||||
const helpers = require('../www/helpers')(jsUtil, cookieHandler, messages, errorCodes);
|
||||
const helpers = require('../www/helpers')(null, jsUtil, cookieHandler, messages, errorCodes);
|
||||
const urlUtil = require('../www/url-util')(jsUtil);
|
||||
|
||||
return { exec: noop, cookieHandler, urlUtil: urlUtil, helpers, globalConfigs, errorCodes };
|
||||
@@ -265,13 +268,13 @@ describe('Common helpers', function () {
|
||||
const init = require('../www/helpers');
|
||||
init.debug = true;
|
||||
|
||||
const helpers = init(null, null, null);
|
||||
const helpers = init(null, null, null, null, null, null);
|
||||
|
||||
it('merges empty header sets correctly', () => {
|
||||
helpers.mergeHeaders({}, {}).should.eql({});
|
||||
});
|
||||
|
||||
it('merges ssimple header sets without collision correctly', () => {
|
||||
it('merges simple header sets without collision correctly', () => {
|
||||
helpers.mergeHeaders({ a: 1 }, { b: 2 }).should.eql({ a: 1, b: 2 });
|
||||
});
|
||||
|
||||
@@ -282,13 +285,13 @@ describe('Common helpers', function () {
|
||||
|
||||
describe('getCookieHeader(url)', function () {
|
||||
it('resolves cookie header correctly when no cookie is set #198', () => {
|
||||
const helpers = require('../www/helpers')(null, { getCookieString: () => '' }, null);
|
||||
const helpers = require('../www/helpers')(null, null, { getCookieString: () => '' }, null);
|
||||
|
||||
helpers.getCookieHeader('http://ilkimen.net').should.eql({});
|
||||
});
|
||||
|
||||
it('resolves cookie header correctly when a cookie is set', () => {
|
||||
const helpers = require('../www/helpers')(null, { getCookieString: () => 'cookie=value' }, null);
|
||||
const helpers = require('../www/helpers')(null, null, { getCookieString: () => 'cookie=value' }, null);
|
||||
|
||||
helpers.getCookieHeader('http://ilkimen.net').should.eql({ Cookie: 'cookie=value' });
|
||||
});
|
||||
@@ -297,7 +300,7 @@ describe('Common helpers', function () {
|
||||
describe('checkClientAuthOptions()', function () {
|
||||
const jsUtil = require('../www/js-util');
|
||||
const messages = require('../www/messages');
|
||||
const helpers = require('../www/helpers')(jsUtil, null, messages);
|
||||
const helpers = require('../www/helpers')(null, jsUtil, null, messages);
|
||||
|
||||
it('returns options object with empty values when mode is "none" and no options are given', () => {
|
||||
helpers.checkClientAuthOptions('none').should.eql({
|
||||
@@ -362,7 +365,7 @@ describe('Common helpers', function () {
|
||||
describe('handleMissingOptions()', function () {
|
||||
const jsUtil = require('../www/js-util');
|
||||
const messages = require('../www/messages');
|
||||
const helpers = require('../www/helpers')(jsUtil, null, messages);
|
||||
const helpers = require('../www/helpers')(null, jsUtil, null, messages);
|
||||
const mockGlobals = {
|
||||
headers: {},
|
||||
serializer: 'urlencoded',
|
||||
@@ -394,7 +397,7 @@ describe('Common helpers', function () {
|
||||
};
|
||||
|
||||
it('does not change response data if it is an ArrayBuffer', () => {
|
||||
const helpers = require('../www/helpers')(jsUtil, null, messages, null, errorCodes);
|
||||
const helpers = require('../www/helpers')(null, jsUtil, null, messages, null, errorCodes);
|
||||
const buffer = new ArrayBuffer(5);
|
||||
const handler = helpers.injectRawResponseHandler(
|
||||
'arraybuffer',
|
||||
@@ -406,7 +409,7 @@ describe('Common helpers', function () {
|
||||
|
||||
it('does not change response data if it is a Blob', () => {
|
||||
const fakeJsUtil = { getTypeOf: () => 'Blob' };
|
||||
const helpers = require('../www/helpers')(fakeJsUtil, null, messages, null, errorCodes);
|
||||
const helpers = require('../www/helpers')(null, fakeJsUtil, null, messages, null, errorCodes);
|
||||
const handler = helpers.injectRawResponseHandler(
|
||||
'blob',
|
||||
response => response.data.should.be.equal('fakeData')
|
||||
@@ -416,7 +419,7 @@ describe('Common helpers', function () {
|
||||
});
|
||||
|
||||
it('does not change response data if response type is "text"', () => {
|
||||
const helpers = require('../www/helpers')(jsUtil, null, messages, null, errorCodes);
|
||||
const helpers = require('../www/helpers')(null, jsUtil, null, messages, null, errorCodes);
|
||||
const example = 'exampleText';
|
||||
const handler = helpers.injectRawResponseHandler(
|
||||
'text',
|
||||
@@ -428,7 +431,7 @@ describe('Common helpers', function () {
|
||||
|
||||
it('handles response type "json" correctly', () => {
|
||||
const fakeData = { myString: 'bla', myNumber: 10 };
|
||||
const helpers = require('../www/helpers')(jsUtil, null, messages, null, errorCodes);
|
||||
const helpers = require('../www/helpers')(null, jsUtil, null, messages, null, errorCodes);
|
||||
const handler = helpers.injectRawResponseHandler(
|
||||
'json',
|
||||
response => response.data.should.be.eql(fakeData)
|
||||
@@ -438,7 +441,7 @@ describe('Common helpers', function () {
|
||||
});
|
||||
|
||||
it('handles response type "arraybuffer" correctly', () => {
|
||||
const helpers = require('../www/helpers')(jsUtil, null, messages, fakeBase64, errorCodes);
|
||||
const helpers = require('../www/helpers')(null, jsUtil, null, messages, fakeBase64, errorCodes);
|
||||
const handler = helpers.injectRawResponseHandler(
|
||||
'arraybuffer',
|
||||
response => response.data.should.be.equal('fakeArrayBuffer')
|
||||
@@ -448,7 +451,7 @@ describe('Common helpers', function () {
|
||||
});
|
||||
|
||||
it('handles response type "blob" correctly', () => {
|
||||
const helpers = require('../www/helpers')(jsUtil, null, messages, fakeBase64, errorCodes);
|
||||
const helpers = require('../www/helpers')(null, jsUtil, null, messages, fakeBase64, errorCodes);
|
||||
const handler = helpers.injectRawResponseHandler(
|
||||
'blob',
|
||||
(response) => {
|
||||
@@ -462,7 +465,7 @@ describe('Common helpers', function () {
|
||||
});
|
||||
|
||||
it('calls failure callback when post-processing fails', () => {
|
||||
const helpers = require('../www/helpers')(jsUtil, null, messages, fakeBase64, errorCodes);
|
||||
const helpers = require('../www/helpers')(null, jsUtil, null, messages, fakeBase64, errorCodes);
|
||||
const handler = helpers.injectRawResponseHandler(
|
||||
'json',
|
||||
null,
|
||||
@@ -479,7 +482,7 @@ describe('Common helpers', function () {
|
||||
describe('checkUploadFileOptions()', function () {
|
||||
const jsUtil = require('../www/js-util');
|
||||
const messages = require('../www/messages');
|
||||
const helpers = require('../www/helpers')(jsUtil, null, messages, null, null);
|
||||
const helpers = require('../www/helpers')(null, jsUtil, null, messages, null, null);
|
||||
|
||||
it('checks valid file options correctly', () => {
|
||||
const opts = {
|
||||
@@ -508,4 +511,66 @@ describe('Common helpers', function () {
|
||||
(() => helpers.checkUploadFileOptions(['file://path/to/file.png'], [1])).should.throw(messages.NAMES_TYPE_MISMATCH);
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
describe('getProcessedData()', function () {
|
||||
const jsUtil = require('../www/js-util');
|
||||
const messages = require('../www/messages');
|
||||
const dependencyValidator = require('../www/dependency-validator')(FormDataMock, null, messages);
|
||||
const helpers = require('../www/helpers')({ FormData: FormDataMock }, jsUtil, null, messages, null, null, dependencyValidator);
|
||||
|
||||
it('throws an error when given data does not match allowed data types', () => {
|
||||
(() => helpers.getProcessedData('myString', 'urlencoded')).should.throw(messages.TYPE_MISMATCH_DATA);
|
||||
(() => helpers.getProcessedData('myString', 'json')).should.throw(messages.TYPE_MISMATCH_DATA);
|
||||
(() => helpers.getProcessedData({}, 'utf8')).should.throw(messages.TYPE_MISMATCH_DATA);
|
||||
});
|
||||
|
||||
it('throws an error when needed Web API is not available', () => {
|
||||
const helpers = require('../www/helpers')({}, jsUtil, null, messages, null, null);
|
||||
(() => helpers.getProcessedData(null, 'multipart')).should.throw(`${messages.INSTANCE_TYPE_NOT_SUPPORTED} FormData`);
|
||||
});
|
||||
|
||||
it('throws an error when given data does not match allowed instance types', () => {
|
||||
(() => helpers.getProcessedData('myString', 'multipart')).should.throw(messages.INSTANCE_TYPE_MISMATCH_DATA);
|
||||
});
|
||||
|
||||
it('processes data correctly when serializer "utf8" is configured', () => {
|
||||
helpers.getProcessedData('myString', 'utf8').should.be.eql({text: 'myString'});
|
||||
});
|
||||
|
||||
it('processes data correctly when serializer "multipart" is configured', () => {
|
||||
helpers.getProcessedData(new FormDataMock(), 'multipart');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Dependency Validator', function () {
|
||||
const messages = require('../www/messages');
|
||||
|
||||
describe('logWarnings()', function () {
|
||||
it('logs a warning message if FormData API is not supported', function () {
|
||||
const console = new ConsoleMock();
|
||||
|
||||
require('../www/dependency-validator')(undefined, console, messages).logWarnings();
|
||||
|
||||
console.messageList.length.should.be.equal(1);
|
||||
console.messageList[0].type.should.be.equal('warn');
|
||||
console.messageList[0].message.should.be.eql([messages.MISSING_FORMDATA_API]);
|
||||
});
|
||||
|
||||
it('logs a warning message if FormData.entries() API is not supported', function () {
|
||||
const console = new ConsoleMock();
|
||||
|
||||
require('../www/dependency-validator')({}, console, messages).logWarnings();
|
||||
|
||||
console.messageList.length.should.be.equal(1);
|
||||
console.messageList[0].type.should.be.equal('warn');
|
||||
console.messageList[0].message.should.be.eql([messages.MISSING_FORMDATA_ENTRIES_API]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkFormDataApi()', function () {
|
||||
it('throws an error if FormData.entries() API is not supported', function () {
|
||||
(() => require('../www/dependency-validator')(null, null, messages).checkFormDataApi()).should.throw(messages.MISSING_FORMDATA_ENTRIES_API);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
module.exports = class ConsoleMock {
|
||||
constructor() {
|
||||
this.messageList = [];
|
||||
}
|
||||
|
||||
debug(...message) { this.messageList.push({ type: 'debug', message }); }
|
||||
error(...message) { this.messageList.push({ type: 'error', message }); }
|
||||
log(...message) { this.messageList.push({ type: 'log', message }); }
|
||||
info(...message) { this.messageList.push({ type: 'info', message }); }
|
||||
warn(...message) { this.messageList.push({ type: 'warn', message }); }
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
module.exports = class FormDataMock {
|
||||
append() {
|
||||
throw new Error('Not implemented in FormDataMock.');
|
||||
}
|
||||
|
||||
delete() {
|
||||
throw new Error('Not implemented in FormDataMock.');
|
||||
}
|
||||
|
||||
entries() {
|
||||
throw new Error('Not implemented in FormDataMock.');
|
||||
}
|
||||
|
||||
forEach() {
|
||||
throw new Error('Not implemented in FormDataMock.');
|
||||
}
|
||||
|
||||
get() {
|
||||
throw new Error('Not implemented in FormDataMock.');
|
||||
}
|
||||
|
||||
getAll() {
|
||||
throw new Error('Not implemented in FormDataMock.');
|
||||
}
|
||||
|
||||
has() {
|
||||
throw new Error('Not implemented in FormDataMock.');
|
||||
}
|
||||
|
||||
keys() {
|
||||
throw new Error('Not implemented in FormDataMock.');
|
||||
}
|
||||
|
||||
set() {
|
||||
throw new Error('Not implemented in FormDataMock.');
|
||||
}
|
||||
|
||||
values() {
|
||||
throw new Error('Not implemented in FormDataMock.');
|
||||
}
|
||||
};
|
||||
@@ -14,8 +14,11 @@ var ToughCookie = require(pluginId + '.tough-cookie');
|
||||
var lodash = require(pluginId + '.lodash');
|
||||
var WebStorageCookieStore = require(pluginId + '.local-storage-store')(ToughCookie, lodash);
|
||||
var cookieHandler = require(pluginId + '.cookie-handler')(window.localStorage, ToughCookie, WebStorageCookieStore);
|
||||
var helpers = require(pluginId + '.helpers')(jsUtil, cookieHandler, messages, base64, errorCodes);
|
||||
var dependencyValidator = require(pluginId + '.dependency-validator')(window.FormData, window.console, messages);
|
||||
var helpers = require(pluginId + '.helpers')(window, jsUtil, cookieHandler, messages, base64, errorCodes, dependencyValidator);
|
||||
var urlUtil = require(pluginId + '.url-util')(jsUtil);
|
||||
var publicInterface = require(pluginId + '.public-interface')(exec, cookieHandler, urlUtil, helpers, globalConfigs, errorCodes);
|
||||
|
||||
dependencyValidator.logWarnings();
|
||||
|
||||
module.exports = publicInterface;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
module.exports = function init(FormData, console, messages) {
|
||||
var interface = {
|
||||
checkFormDataApi: checkFormDataApi,
|
||||
logWarnings: logWarnings,
|
||||
};
|
||||
|
||||
return interface;
|
||||
|
||||
function logWarnings() {
|
||||
if (!FormData) {
|
||||
console.warn(messages.MISSING_FORMDATA_API);
|
||||
} else if (!FormData.prototype || !FormData.prototype.entries) {
|
||||
console.warn(messages.MISSING_FORMDATA_ENTRIES_API);
|
||||
}
|
||||
}
|
||||
|
||||
function checkFormDataApi() {
|
||||
if (!FormData || !FormData.prototype || !FormData.prototype.entries) {
|
||||
throw new Error(messages.MISSING_FORMDATA_ENTRIES_API);
|
||||
}
|
||||
}
|
||||
};
|
||||
+26
-5
@@ -1,5 +1,5 @@
|
||||
module.exports = function init(jsUtil, cookieHandler, messages, base64, errorCodes) {
|
||||
var validSerializers = ['urlencoded', 'json', 'utf8'];
|
||||
module.exports = function init(global, jsUtil, cookieHandler, messages, base64, errorCodes, dependencyValidator) {
|
||||
var validSerializers = ['urlencoded', 'json', 'utf8', 'multipart'];
|
||||
var validCertModes = ['default', 'nocheck', 'pinned', 'legacy'];
|
||||
var validClientAuthModes = ['none', 'systemstore', 'buffer'];
|
||||
var validHttpMethods = ['get', 'put', 'post', 'patch', 'head', 'delete', 'upload', 'download'];
|
||||
@@ -270,7 +270,7 @@ module.exports = function init(jsUtil, cookieHandler, messages, base64, errorCod
|
||||
entry.isFile = rawEntry.isFile;
|
||||
entry.name = rawEntry.name;
|
||||
entry.fullPath = rawEntry.fullPath;
|
||||
entry.filesystem = new FileSystem(rawEntry.filesystemName || (rawEntry.filesystem == window.PERSISTENT ? 'persistent' : 'temporary'));
|
||||
entry.filesystem = new FileSystem(rawEntry.filesystemName || (rawEntry.filesystem == global.PERSISTENT ? 'persistent' : 'temporary'));
|
||||
entry.nativeURL = rawEntry.nativeURL;
|
||||
|
||||
return entry;
|
||||
@@ -363,16 +363,31 @@ module.exports = function init(jsUtil, cookieHandler, messages, base64, errorCod
|
||||
return ['String'];
|
||||
case 'urlencoded':
|
||||
return ['Object'];
|
||||
default:
|
||||
case 'json':
|
||||
return ['Array', 'Object'];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function getAllowedInstanceType(dataSerializer) {
|
||||
return dataSerializer === 'multipart' ? 'FormData' : null;
|
||||
}
|
||||
|
||||
function getProcessedData(data, dataSerializer) {
|
||||
var currentDataType = jsUtil.getTypeOf(data);
|
||||
var allowedDataTypes = getAllowedDataTypes(dataSerializer);
|
||||
var allowedInstanceType = getAllowedInstanceType(dataSerializer);
|
||||
|
||||
if (allowedDataTypes.indexOf(currentDataType) === -1) {
|
||||
if (allowedInstanceType && !global[allowedInstanceType]) {
|
||||
throw new Error(messages.INSTANCE_TYPE_NOT_SUPPORTED + ' ' + allowedInstanceType);
|
||||
}
|
||||
|
||||
if (allowedInstanceType && !(data instanceof global[allowedInstanceType])) {
|
||||
throw new Error(messages.INSTANCE_TYPE_MISMATCH_DATA + ' ' + allowedInstanceType);
|
||||
}
|
||||
|
||||
if (!allowedInstanceType && allowedDataTypes.indexOf(currentDataType) === -1) {
|
||||
throw new Error(messages.TYPE_MISMATCH_DATA + ' ' + allowedDataTypes.join(', '));
|
||||
}
|
||||
|
||||
@@ -380,6 +395,12 @@ module.exports = function init(jsUtil, cookieHandler, messages, base64, errorCod
|
||||
data = { text: data };
|
||||
}
|
||||
|
||||
if (dataSerializer === 'multipart') {
|
||||
dependencyValidator.checkFormDataApi();
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -2,6 +2,8 @@ module.exports = {
|
||||
ADDING_COOKIES_NOT_SUPPORTED: 'advanced-http: "setHeader" does not support adding cookies, please use "setCookie" function instead',
|
||||
EMPTY_FILE_PATHS: 'advanced-http: "filePaths" option array must not be empty, <filePaths: string[]>',
|
||||
EMPTY_NAMES: 'advanced-http: "names" option array must not be empty, <names: string[]>',
|
||||
INSTANCE_TYPE_MISMATCH_DATA: 'advanced-http: "data" option is configured to support only following instance types:',
|
||||
INSTANCE_TYPE_NOT_SUPPORTED: 'advanced-http: this webview does not support following Web API which is needed for this plugin:',
|
||||
INVALID_CLIENT_AUTH_ALIAS: 'advanced-http: invalid client certificate alias, needs to be a string or undefined, <alias: string | undefined>',
|
||||
INVALID_CLIENT_AUTH_MODE: 'advanced-http: invalid client certificate authentication mode, supported modes are:',
|
||||
INVALID_CLIENT_AUTH_OPTIONS: 'advanced-http: invalid client certificate authentication options, needs to be an dictionary style object',
|
||||
@@ -17,8 +19,10 @@ module.exports = {
|
||||
INVALID_TIMEOUT_VALUE: 'advanced-http: invalid timeout value, needs to be a positive numeric value, <timeout: number>',
|
||||
MANDATORY_FAIL: 'advanced-http: missing mandatory "onFail" callback function',
|
||||
MANDATORY_SUCCESS: 'advanced-http: missing mandatory "onSuccess" callback function',
|
||||
MISSING_FORMDATA_API: 'advanced-http: FormData API is not supported in this webview. If you want to use "multipart/form-data" requests, you need to load a polyfill library before loading this plugin. Check out https://github.com/silkimen/cordova-plugin-advanced-http/wiki/FormData-API-requirements for more info.',
|
||||
MISSING_FORMDATA_ENTRIES_API: 'advanced-http: This webview does not implement FormData API specification correctly, FormData.entries() is missing. If you want to use "multipart/form-data" requests, you need to load a polyfill library before loading this plugin. Check out https://github.com/silkimen/cordova-plugin-advanced-http/wiki/FormData-API-requirements for more info.',
|
||||
POST_PROCESSING_FAILED: 'advanced-http: an error occured during post processing response:',
|
||||
TYPE_MISMATCH_DATA: 'advanced-http: "data" option supports only following data types:',
|
||||
TYPE_MISMATCH_DATA: 'advanced-http: "data" option is configured to support only following data types:',
|
||||
TYPE_MISMATCH_FILE_PATHS: 'advanced-http: "filePaths" option needs to be an string array, <filePaths: string[]>',
|
||||
TYPE_MISMATCH_HEADERS: 'advanced-http: "headers" option needs to be an dictionary style object with string values, <headers: {[key: string]: string}>',
|
||||
TYPE_MISMATCH_NAMES: 'advanced-http: "names" option needs to be an string array, <names: string[]>',
|
||||
|
||||
Reference in New Issue
Block a user