UNPKG

metaapi.cloud-sdk

Version:

SDK for MetaApi, a professional cloud forex API which includes MetaTrader REST API and MetaTrader websocket API. Supports both MetaTrader 5 (MT5) and MetaTrader 4 (MT4). CopyFactory copy trading API included. (https://metaapi.cloud)

97 lines (96 loc) 13.8 kB
'use strict'; import * as testHelpers from './testHelpers'; import { AssertionError } from 'assert'; import util from 'util'; import 'should'; /** * Asserts that a stub or apy called specified number of times with args matched specified ones * @param {Function} spy Sinon stub or spy * @param {Number} calls Expected number of calls * @param {Array} args Expected call arguments * @throws {AssertionError} If assertion failed */ export function callCountWithMatch(spy, calls, ...args) { if (!spy.isSinonProxy) { throw new AssertionError({ message: 'Given function is not a sinon spy' }); } let matchedCalls = testHelpers.getCallsWithMatch(spy, ...args); if (matchedCalls.length !== calls) { throw Object.assign(new AssertionError({ message: `Spy expected to be called ${calls} times with specified arguments but was called ` + `${matchedCalls.length} times with them of ${spy.callCount} total calls` }), { callArgs: util.inspect(spy.args, { depth: 3 }) }); } } /** * Asserts that a stub or apy called specified number of times with args that deep equal to specified ones * @param {Function} spy Sinon stub or spy * @param {Number} calls Expected number of calls * @param {Array} args Expected call arguments * @throws {AssertionError} If assertion failed */ export function callCountWithExactly(spy, calls, ...args) { if (!spy.isSinonProxy) { throw new AssertionError({ message: 'Given function is not a sinon spy' }); } let matchedCalls = testHelpers.getCallsWithExactly(spy, ...args); matchedCalls.length.should.equal(calls, `Spy expected to be called ${calls} times with specified arguments ` + `but was called ${matchedCalls.length} times with them of ${spy.callCount} total calls`); } /** * Asserts that array matches to expected one with and the lengths are equal * @param {Array} actualArray Actual array to match * @param {Array} expectedArray Expected array to match to * @throws {AssertionError} If assertion failed */ export function arrayMatchWithEqualLength(actualArray, expectedArray) { actualArray.should.match(expectedArray); actualArray.length.should.equal(expectedArray.length); } /** * Sinon's callOrder seems to have some bug giving incorrect assertion, so this is a manual implementation * @param spyCalls spy calls * @throws assertion error */ export function callOrder(spyCalls) { let callIds = spyCalls.map((call, index)=>{ const label = call.label || call.spy.name || 'default'; let sinonCall = call.spy.getCall(call.call); if (!sinonCall) { throw new AssertionError({ message: `Call ${index} (${label}) does not exist` }); } return { id: sinonCall.callId, label }; }); let previousCallId; for(let index = 0; index < spyCalls.length; ++index){ if (previousCallId !== undefined && callIds[index].id < previousCallId.id) { throw new AssertionError({ message: `Wrong call order detected in call ids ${callIds.map((id)=>`\n${id.id} (${id.label})`)}`, expected: `Call id larger than the previous call ${previousCallId}`, actual: callIds[index] }); } if (spyCalls[index].matchArgs) { try { spyCalls[index].spy.getCall(spyCalls[index].call).args.should.match(spyCalls[index].matchArgs); } catch (err) { throw Object.assign(new AssertionError({ message: `Call ${index} (${callIds[index].label}) args do not match` }), { index, label: callIds[index].label, cause: err }); } } previousCallId = callIds[index]; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCAqIGFzIHRlc3RIZWxwZXJzIGZyb20gJy4vdGVzdEhlbHBlcnMnO1xuaW1wb3J0IHtBc3NlcnRpb25FcnJvcn0gZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7RGVlcFBhcnRpYWx9IGZyb20gJy4uLy4uL3R5cGVzL3V0aWwnO1xuaW1wb3J0IHR5cGUgc2lub24gZnJvbSAnc2lub24nO1xuaW1wb3J0IHV0aWwgZnJvbSAndXRpbCc7XG5pbXBvcnQgJ3Nob3VsZCc7XG5cbi8qKlxuICogQXNzZXJ0cyB0aGF0IGEgc3R1YiBvciBhcHkgY2FsbGVkIHNwZWNpZmllZCBudW1iZXIgb2YgdGltZXMgd2l0aCBhcmdzIG1hdGNoZWQgc3BlY2lmaWVkIG9uZXNcbiAqIEBwYXJhbSB7RnVuY3Rpb259IHNweSBTaW5vbiBzdHViIG9yIHNweVxuICogQHBhcmFtIHtOdW1iZXJ9IGNhbGxzIEV4cGVjdGVkIG51bWJlciBvZiBjYWxsc1xuICogQHBhcmFtIHtBcnJheX0gYXJncyBFeHBlY3RlZCBjYWxsIGFyZ3VtZW50c1xuICogQHRocm93cyB7QXNzZXJ0aW9uRXJyb3J9IElmIGFzc2VydGlvbiBmYWlsZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhbGxDb3VudFdpdGhNYXRjaDxTcHkgZXh0ZW5kcyBzaW5vbi5TaW5vblNweT4oXG4gIHNweTogU3B5LCBjYWxsczogbnVtYmVyLCAuLi5hcmdzOiBEZWVwUGFydGlhbDxQYXJhbWV0ZXJzPFNweT4+XG4pIHtcbiAgaWYgKCEoc3B5IGFzIGFueSkuaXNTaW5vblByb3h5KSB7XG4gICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKHttZXNzYWdlOiAnR2l2ZW4gZnVuY3Rpb24gaXMgbm90IGEgc2lub24gc3B5J30pO1xuICB9XG4gIGxldCBtYXRjaGVkQ2FsbHMgPSB0ZXN0SGVscGVycy5nZXRDYWxsc1dpdGhNYXRjaChzcHksIC4uLmFyZ3MpO1xuICBpZiAobWF0Y2hlZENhbGxzLmxlbmd0aCAhPT0gY2FsbHMpIHtcbiAgICB0aHJvdyBPYmplY3QuYXNzaWduKFxuICAgICAgbmV3IEFzc2VydGlvbkVycm9yKHttZXNzYWdlOiBgU3B5IGV4cGVjdGVkIHRvIGJlIGNhbGxlZCAke2NhbGxzfSB0aW1lcyB3aXRoIHNwZWNpZmllZCBhcmd1bWVudHMgYnV0IHdhcyBjYWxsZWQgYCArXG4gICAgICAgIGAke21hdGNoZWRDYWxscy5sZW5ndGh9IHRpbWVzIHdpdGggdGhlbSBvZiAke3NweS5jYWxsQ291bnR9IHRvdGFsIGNhbGxzYH0pLFxuICAgICAge2NhbGxBcmdzOiB1dGlsLmluc3BlY3Qoc3B5LmFyZ3MsIHtkZXB0aDogM30pfVxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBBc3NlcnRzIHRoYXQgYSBzdHViIG9yIGFweSBjYWxsZWQgc3BlY2lmaWVkIG51bWJlciBvZiB0aW1lcyB3aXRoIGFyZ3MgdGhhdCBkZWVwIGVxdWFsIHRvIHNwZWNpZmllZCBvbmVzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBzcHkgU2lub24gc3R1YiBvciBzcHlcbiAqIEBwYXJhbSB7TnVtYmVyfSBjYWxscyBFeHBlY3RlZCBudW1iZXIgb2YgY2FsbHNcbiAqIEBwYXJhbSB7QXJyYXl9IGFyZ3MgRXhwZWN0ZWQgY2FsbCBhcmd1bWVudHNcbiAqIEB0aHJvd3Mge0Fzc2VydGlvbkVycm9yfSBJZiBhc3NlcnRpb24gZmFpbGVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjYWxsQ291bnRXaXRoRXhhY3RseTxTcHkgZXh0ZW5kcyBzaW5vbi5TaW5vblNweT4oc3B5OiBTcHksIGNhbGxzOiBudW1iZXIsIC4uLmFyZ3M6IFBhcmFtZXRlcnM8U3B5Pikge1xuICBpZiAoIShzcHkgYXMgYW55KS5pc1Npbm9uUHJveHkpIHtcbiAgICB0aHJvdyBuZXcgQXNzZXJ0aW9uRXJyb3Ioe21lc3NhZ2U6ICdHaXZlbiBmdW5jdGlvbiBpcyBub3QgYSBzaW5vbiBzcHknfSk7XG4gIH1cbiAgbGV0IG1hdGNoZWRDYWxscyA9IHRlc3RIZWxwZXJzLmdldENhbGxzV2l0aEV4YWN0bHkoc3B5LCAuLi5hcmdzIGFzIERlZXBQYXJ0aWFsPFBhcmFtZXRlcnM8U3B5Pj4pO1xuICBtYXRjaGVkQ2FsbHMubGVuZ3RoLnNob3VsZC5lcXVhbChjYWxscywgYFNweSBleHBlY3RlZCB0byBiZSBjYWxsZWQgJHtjYWxsc30gdGltZXMgd2l0aCBzcGVjaWZpZWQgYXJndW1lbnRzIGAgK1xuICAgIGBidXQgd2FzIGNhbGxlZCAke21hdGNoZWRDYWxscy5sZW5ndGh9IHRpbWVzIHdpdGggdGhlbSBvZiAke3NweS5jYWxsQ291bnR9IHRvdGFsIGNhbGxzYCk7XG59XG5cbi8qKlxuICogQXNzZXJ0cyB0aGF0IGFycmF5IG1hdGNoZXMgdG8gZXhwZWN0ZWQgb25lIHdpdGggYW5kIHRoZSBsZW5ndGhzIGFyZSBlcXVhbCBcbiAqIEBwYXJhbSB7QXJyYXl9IGFjdHVhbEFycmF5IEFjdHVhbCBhcnJheSB0byBtYXRjaFxuICogQHBhcmFtIHtBcnJheX0gZXhwZWN0ZWRBcnJheSBFeHBlY3RlZCBhcnJheSB0byBtYXRjaCB0b1xuICogQHRocm93cyB7QXNzZXJ0aW9uRXJyb3J9IElmIGFzc2VydGlvbiBmYWlsZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFycmF5TWF0Y2hXaXRoRXF1YWxMZW5ndGgoYWN0dWFsQXJyYXksIGV4cGVjdGVkQXJyYXkpIHtcbiAgYWN0dWFsQXJyYXkuc2hvdWxkLm1hdGNoKGV4cGVjdGVkQXJyYXkpO1xuICBhY3R1YWxBcnJheS5sZW5ndGguc2hvdWxkLmVxdWFsKGV4cGVjdGVkQXJyYXkubGVuZ3RoKTtcbn1cblxuLyoqIFNweSBjYWxsIG9wdGlvbnMgKi9cbmV4cG9ydCB0eXBlIFNweUNhbGw8VEFyZ3MgZXh0ZW5kcyByZWFkb25seSBhbnlbXT4gPSB7XG4gIC8qKiBTaW5vbiBzcHkgKi9cbiAgc3B5OiBzaW5vbi5TaW5vblNweTxUQXJncz4sXG4gIC8qKiBDYWxsIGluZGV4ICovXG4gIGNhbGw6IG51bWJlcixcbiAgLyoqIElmIHNwZWNpZmllZCwgYXNzZXJ0cyBhcmdzIG1hdGNoICovXG4gIG1hdGNoQXJncz86IERlZXBQYXJ0aWFsPFRBcmdzPixcbiAgLyoqIExvZ2dpbmcgbGFiZWwuIERlZmF1bHRzIHRvIGBzcHlgIGZ1bmN0aW9uIG5hbWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBkZWZhdWx0YCAqL1xuICBsYWJlbD86IHN0cmluZ1xufTtcblxuLyoqXG4gKiBTaW5vbidzIGNhbGxPcmRlciBzZWVtcyB0byBoYXZlIHNvbWUgYnVnIGdpdmluZyBpbmNvcnJlY3QgYXNzZXJ0aW9uLCBzbyB0aGlzIGlzIGEgbWFudWFsIGltcGxlbWVudGF0aW9uXG4gKiBAcGFyYW0gc3B5Q2FsbHMgc3B5IGNhbGxzXG4gKiBAdGhyb3dzIGFzc2VydGlvbiBlcnJvclxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FsbE9yZGVyKHNweUNhbGxzOiBTcHlDYWxsPGFueT5bXSkge1xuICB0eXBlIENhbGxJZCA9IHtpZDogbnVtYmVyLCBsYWJlbDogc3RyaW5nfTtcbiAgbGV0IGNhbGxJZHM6IENhbGxJZFtdID0gc3B5Q2FsbHMubWFwKChjYWxsLCBpbmRleCkgPT4ge1xuICAgIGNvbnN0IGxhYmVsID0gY2FsbC5sYWJlbCB8fCBjYWxsLnNweS5uYW1lIHx8ICdkZWZhdWx0JztcbiAgICBsZXQgc2lub25DYWxsID0gY2FsbC5zcHkuZ2V0Q2FsbChjYWxsLmNhbGwpO1xuICAgIGlmICghc2lub25DYWxsKSB7XG4gICAgICB0aHJvdyBuZXcgQXNzZXJ0aW9uRXJyb3Ioe21lc3NhZ2U6IGBDYWxsICR7aW5kZXh9ICgke2xhYmVsfSkgZG9lcyBub3QgZXhpc3RgfSk7XG4gICAgfVxuICAgIHJldHVybiB7aWQ6IChzaW5vbkNhbGwgYXMgYW55KS5jYWxsSWQsIGxhYmVsfTtcbiAgfSk7XG4gIGxldCBwcmV2aW91c0NhbGxJZDogQ2FsbElkO1xuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgc3B5Q2FsbHMubGVuZ3RoOyArK2luZGV4KSB7XG4gICAgaWYgKHByZXZpb3VzQ2FsbElkICE9PSB1bmRlZmluZWQgJiYgY2FsbElkc1tpbmRleF0uaWQgPCBwcmV2aW91c0NhbGxJZC5pZCkge1xuICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKHtcbiAgICAgICAgbWVzc2FnZTogYFdyb25nIGNhbGwgb3JkZXIgZGV0ZWN0ZWQgaW4gY2FsbCBpZHMgJHtjYWxsSWRzLm1hcChpZCA9PiBgXFxuJHtpZC5pZH0gKCR7aWQubGFiZWx9KWApfWAsXG4gICAgICAgIGV4cGVjdGVkOiBgQ2FsbCBpZCBsYXJnZXIgdGhhbiB0aGUgcHJldmlvdXMgY2FsbCAke3ByZXZpb3VzQ2FsbElkfWAsXG4gICAgICAgIGFjdHVhbDogY2FsbElkc1tpbmRleF1cbiAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAoc3B5Q2FsbHNbaW5kZXhdLm1hdGNoQXJncykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgc3B5Q2FsbHNbaW5kZXhdLnNweS5nZXRDYWxsKHNweUNhbGxzW2luZGV4XS5jYWxsKS5hcmdzLnNob3VsZC5tYXRjaChzcHlDYWxsc1tpbmRleF0ubWF0Y2hBcmdzKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICB0aHJvdyBPYmplY3QuYXNzaWduKFxuICAgICAgICAgIG5ldyBBc3NlcnRpb25FcnJvcih7bWVzc2FnZTogYENhbGwgJHtpbmRleH0gKCR7Y2FsbElkc1tpbmRleF0ubGFiZWx9KSBhcmdzIGRvIG5vdCBtYXRjaGB9KSxcbiAgICAgICAgICB7aW5kZXgsIGxhYmVsOiBjYWxsSWRzW2luZGV4XS5sYWJlbCwgY2F1c2U6IGVycn1cbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcHJldmlvdXNDYWxsSWQgPSBjYWxsSWRzW2luZGV4XTtcbiAgfVxufVxuIl0sIm5hbWVzIjpbInRlc3RIZWxwZXJzIiwiQXNzZXJ0aW9uRXJyb3IiLCJ1dGlsIiwiY2FsbENvdW50V2l0aE1hdGNoIiwic3B5IiwiY2FsbHMiLCJhcmdzIiwiaXNTaW5vblByb3h5IiwibWVzc2FnZSIsIm1hdGNoZWRDYWxscyIsImdldENhbGxzV2l0aE1hdGNoIiwibGVuZ3RoIiwiT2JqZWN0IiwiYXNzaWduIiwiY2FsbENvdW50IiwiY2FsbEFyZ3MiLCJpbnNwZWN0IiwiZGVwdGgiLCJjYWxsQ291bnRXaXRoRXhhY3RseSIsImdldENhbGxzV2l0aEV4YWN0bHkiLCJzaG91bGQiLCJlcXVhbCIsImFycmF5TWF0Y2hXaXRoRXF1YWxMZW5ndGgiLCJhY3R1YWxBcnJheSIsImV4cGVjdGVkQXJyYXkiLCJtYXRjaCIsImNhbGxPcmRlciIsInNweUNhbGxzIiwiY2FsbElkcyIsIm1hcCIsImNhbGwiLCJpbmRleCIsImxhYmVsIiwibmFtZSIsInNpbm9uQ2FsbCIsImdldENhbGwiLCJpZCIsImNhbGxJZCIsInByZXZpb3VzQ2FsbElkIiwidW5kZWZpbmVkIiwiZXhwZWN0ZWQiLCJhY3R1YWwiLCJtYXRjaEFyZ3MiLCJlcnIiLCJjYXVzZSJdLCJtYXBwaW5ncyI6IkFBQUE7QUFFQSxZQUFZQSxpQkFBaUIsZ0JBQWdCO0FBQzdDLFNBQVFDLGNBQWMsUUFBTyxTQUFTO0FBR3RDLE9BQU9DLFVBQVUsT0FBTztBQUN4QixPQUFPLFNBQVM7QUFFaEI7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTQyxtQkFDZEMsR0FBUSxFQUFFQyxLQUFhLEVBQUUsR0FBR0MsSUFBa0M7SUFFOUQsSUFBSSxDQUFDLEFBQUNGLElBQVlHLFlBQVksRUFBRTtRQUM5QixNQUFNLElBQUlOLGVBQWU7WUFBQ08sU0FBUztRQUFtQztJQUN4RTtJQUNBLElBQUlDLGVBQWVULFlBQVlVLGlCQUFpQixDQUFDTixRQUFRRTtJQUN6RCxJQUFJRyxhQUFhRSxNQUFNLEtBQUtOLE9BQU87UUFDakMsTUFBTU8sT0FBT0MsTUFBTSxDQUNqQixJQUFJWixlQUFlO1lBQUNPLFNBQVMsQ0FBQywwQkFBMEIsRUFBRUgsTUFBTSwrQ0FBK0MsQ0FBQyxHQUM5RyxDQUFDLEVBQUVJLGFBQWFFLE1BQU0sQ0FB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