How to use keyOnHeader method in mountebank

Best JavaScript code snippet using mountebank

behaviors.js

Source:behaviors.js Github

copy

Full Screen

1'use strict';2/**3 * The functionality behind the _behaviors field in the API, supporting post-processing responses4 * @module5 */6// The following schemas are used by both the lookup and copy behaviors and should be kept consistent7const fromSchema = {8 _required: true,9 _allowedTypes: {10 string: {},11 object: { singleKeyOnly: true }12 },13 _additionalContext: 'the request field to select from'14 },15 intoSchema = {16 _required: true,17 _allowedTypes: { string: {} },18 _additionalContext: 'the token to replace in response fields'19 },20 usingSchema = {21 _required: true,22 _allowedTypes: { object: {} },23 method: {24 _required: true,25 _allowedTypes: { string: { enum: ['regex', 'xpath', 'jsonpath'] } }26 },27 selector: {28 _required: true,29 _allowedTypes: { string: {} }30 }31 },32 validations = {33 wait: {34 _required: true,35 _allowedTypes: { string: {}, number: { nonNegativeInteger: true } }36 },37 repeat: {38 _required: true,39 _allowedTypes: { number: { positiveInteger: true } }40 },41 copy: [{42 from: fromSchema,43 into: intoSchema,44 using: usingSchema45 }],46 lookup: [{47 key: {48 _required: true,49 _allowedTypes: { object: {} },50 from: fromSchema,51 using: usingSchema52 },53 fromDataSource: {54 _required: true,55 _allowedTypes: { object: { singleKeyOnly: true, enum: ['csv'] } },56 csv: {57 _required: false,58 _allowedTypes: { object: {} },59 path: {60 _required: true,61 _allowedTypes: { string: {} },62 _additionalContext: 'the path to the CSV file'63 },64 delimiter: {65 _required: false,66 _allowedTypes: { string: {} },67 _additionalContext: 'the delimiter separator values'68 },69 keyColumn: {70 _required: true,71 _allowedTypes: { string: {} },72 _additionalContext: 'the column header to select against the "key" field'73 }74 }75 },76 into: intoSchema77 }],78 shellTransform: [{79 _required: true,80 _allowedTypes: { string: {} },81 _additionalContext: 'the path to a command line application'82 }],83 decorate: {84 _required: true,85 _allowedTypes: { string: {} },86 _additionalContext: 'a JavaScript function'87 }88 };89/**90 * Validates the behavior configuration and returns all errors91 * @param {Object} config - The behavior configuration92 * @returns {Object} The array of errors93 */94function validate (config) {95 const validator = require('./behaviorsValidator').create();96 return validator.validate(config, validations);97}98/**99 * Waits a specified number of milliseconds before sending the response. Due to the approximate100 * nature of the timer, there is no guarantee that it will wait the given amount, but it will be close.101 * @param {Object} request - The request object102 * @param {Object} responsePromise -kThe promise returning the response103 * @param {number} millisecondsOrFn - The number of milliseconds to wait before returning, or a function returning milliseconds104 * @param {Object} logger - The mountebank logger, useful for debugging105 * @returns {Object} A promise resolving to the response106 */107function wait (request, responsePromise, millisecondsOrFn, logger) {108 if (request.isDryRun) {109 return responsePromise;110 }111 const util = require('util'),112 fn = util.format('(%s)()', millisecondsOrFn),113 Q = require('q'),114 exceptions = require('../util/errors');115 let milliseconds = parseInt(millisecondsOrFn);116 if (isNaN(milliseconds)) {117 try {118 milliseconds = eval(fn);119 }120 catch (error) {121 logger.error('injection X=> ' + error);122 logger.error(' full source: ' + JSON.stringify(fn));123 return Q.reject(exceptions.InjectionError('invalid wait injection',124 { source: millisecondsOrFn, data: error.message }));125 }126 }127 logger.debug('Waiting %s ms...', milliseconds);128 return responsePromise.delay(milliseconds);129}130function quoteForShell (obj) {131 const json = JSON.stringify(obj),132 isWindows = require('os').platform().indexOf('win') === 0,133 util = require('util');134 if (isWindows) {135 // Confused? Me too. All other approaches I tried were spectacular failures136 // in both 1) keeping the JSON as a single CLI arg, and 2) maintaining the inner quotes137 return util.format('"%s"', json.replace(/"/g, '\\"'));138 }139 else {140 return util.format("'%s'", json);141 }142}143function execShell (command, request, response, logger) {144 const Q = require('q'),145 deferred = Q.defer(),146 util = require('util'),147 exec = require('child_process').exec,148 fullCommand = util.format('%s %s %s', command, quoteForShell(request), quoteForShell(response)),149 env = require('../util/helpers').clone(process.env),150 maxBuffer = require('buffer').constants.MAX_STRING_LENGTH;151 logger.debug('Shelling out to %s', command);152 logger.debug(fullCommand);153 // Switched to environment variables because of inconsistencies in Windows shell quoting154 // Leaving the CLI args for backwards compatibility155 env.MB_REQUEST = JSON.stringify(request);156 env.MB_RESPONSE = JSON.stringify(response);157 exec(fullCommand, { env, maxBuffer }, (error, stdout, stderr) => {158 if (error) {159 console.log('ERROR');160 console.log(error);161 if (stderr) {162 logger.error(stderr);163 }164 deferred.reject(error.message);165 }166 else {167 logger.debug("Shell returned '%s'", stdout);168 try {169 deferred.resolve(Q(JSON.parse(stdout)));170 }171 catch (err) {172 deferred.reject(util.format("Shell command returned invalid JSON: '%s'", stdout));173 }174 }175 });176 return deferred.promise;177}178/**179 * Runs the response through a shell function, passing the JSON in as stdin and using180 * stdout as the new response181 * @param {Object} request - Will be the first arg to the command182 * @param {Object} responsePromise - The promise chain for building the response, which will be the second arg183 * @param {string} commandArray - The list of shell commands to execute, in order184 * @param {Object} logger - The mountebank logger, useful in debugging185 * @returns {Object}186 */187function shellTransform (request, responsePromise, commandArray, logger) {188 if (request.isDryRun) {189 return responsePromise;190 }191 // Run them all in sequence192 let result = responsePromise;193 commandArray.forEach(function (command) {194 result = result.then(response => execShell(command, request, response, logger));195 });196 return result;197}198/**199 * Runs the response through a post-processing function provided by the user200 * @param {Object} originalRequest - The request object, in case post-processing depends on it201 * @param {Object} responsePromise - The promise returning the response202 * @param {Function} fn - The function that performs the post-processing203 * @param {Object} logger - The mountebank logger, useful in debugging204 * @returns {Object}205 */206function decorate (originalRequest, responsePromise, fn, logger) {207 if (originalRequest.isDryRun === true) {208 return responsePromise;209 }210 return responsePromise.then(response => {211 const Q = require('q'),212 helpers = require('../util/helpers'),213 config = {214 request: helpers.clone(originalRequest),215 response,216 logger217 },218 injected = `(${fn})(config, response, logger);`,219 exceptions = require('../util/errors'),220 compatibility = require('./compatibility');221 compatibility.downcastInjectionConfig(config);222 try {223 // Support functions that mutate response in place and those224 // that return a new response225 let result = eval(injected);226 if (!result) {227 result = response;228 }229 return Q(result);230 }231 catch (error) {232 logger.error('injection X=> ' + error);233 logger.error(' full source: ' + JSON.stringify(injected));234 logger.error(' config: ' + JSON.stringify(config));235 return Q.reject(exceptions.InjectionError('invalid decorator injection', { source: injected, data: error.message }));236 }237 });238}239function getKeyIgnoringCase (obj, expectedKey) {240 return Object.keys(obj).find(key => {241 if (key.toLowerCase() === expectedKey.toLowerCase()) {242 return key;243 }244 else {245 return undefined;246 }247 });248}249function getFrom (obj, from) {250 const isObject = require('../util/helpers').isObject;251 if (typeof obj === 'undefined') {252 return undefined;253 }254 else if (isObject(from)) {255 const keys = Object.keys(from);256 return getFrom(obj[keys[0]], from[keys[0]]);257 }258 else {259 const result = obj[getKeyIgnoringCase(obj, from)],260 util = require('util');261 // Some request fields, like query parameters, can be multi-valued262 if (util.isArray(result)) {263 return result[0];264 }265 else {266 return result;267 }268 }269}270function regexFlags (options) {271 let result = '';272 if (options && options.ignoreCase) {273 result += 'i';274 }275 if (options && options.multiline) {276 result += 'm';277 }278 return result;279}280function getMatches (selectionFn, selector, logger) {281 const matches = selectionFn();282 if (matches && matches.length > 0) {283 return matches;284 }285 else {286 logger.debug('No match for "%s"', selector);287 return [];288 }289}290function regexValue (from, config, logger) {291 const regex = new RegExp(config.using.selector, regexFlags(config.using.options)),292 selectionFn = () => regex.exec(from);293 return getMatches(selectionFn, regex, logger);294}295function xpathValue (from, config, logger) {296 const selectionFn = () => {297 const xpath = require('./xpath');298 return xpath.select(config.using.selector, config.using.ns, from, logger);299 };300 return getMatches(selectionFn, config.using.selector, logger);301}302function jsonpathValue (from, config, logger) {303 const selectionFn = () => {304 const jsonpath = require('./jsonpath');305 return jsonpath.select(config.using.selector, from, logger);306 };307 return getMatches(selectionFn, config.using.selector, logger);308}309function globalStringReplace (str, substring, newSubstring, logger) {310 if (substring !== newSubstring) {311 logger.debug('Replacing %s with %s', JSON.stringify(substring), JSON.stringify(newSubstring));312 return str.split(substring).join(newSubstring);313 }314 else {315 return str;316 }317}318function globalObjectReplace (obj, replacer) {319 const isObject = require('../util/helpers').isObject;320 Object.keys(obj).forEach(key => {321 if (typeof obj[key] === 'string') {322 obj[key] = replacer(obj[key]);323 }324 else if (isObject(obj[key])) {325 globalObjectReplace(obj[key], replacer);326 }327 });328}329function replaceArrayValuesIn (response, token, values, logger) {330 const replacer = field => {331 values.forEach(function (replacement, index) {332 // replace ${TOKEN}[1] with indexed element333 const util = require('util'),334 indexedToken = util.format('%s[%s]', token, index);335 field = globalStringReplace(field, indexedToken, replacement, logger);336 });337 if (values.length > 0) {338 // replace ${TOKEN} with first element339 field = globalStringReplace(field, token, values[0], logger);340 }341 return field;342 };343 globalObjectReplace(response, replacer);344}345/**346 * Copies a value from the request and replaces response tokens with that value347 * @param {Object} originalRequest - The request object, in case post-processing depends on it348 * @param {Object} responsePromise - The promise returning the response349 * @param {Function} copyArray - The list of values to copy350 * @param {Object} logger - The mountebank logger, useful in debugging351 * @returns {Object}352 */353function copy (originalRequest, responsePromise, copyArray, logger) {354 return responsePromise.then(response => {355 const Q = require('q');356 copyArray.forEach(function (copyConfig) {357 const from = getFrom(originalRequest, copyConfig.from),358 using = copyConfig.using || {},359 fnMap = { regex: regexValue, xpath: xpathValue, jsonpath: jsonpathValue },360 values = fnMap[using.method](from, copyConfig, logger);361 replaceArrayValuesIn(response, copyConfig.into, values, logger);362 });363 return Q(response);364 });365}366function containsKey (headers, keyColumn) {367 const helpers = require('../util/helpers'),368 key = Object.values(headers).find(value => value === keyColumn);369 return helpers.defined(key);370}371function createRowObject (headers, rowArray) {372 const row = {};373 rowArray.forEach(function (value, index) {374 row[headers[index]] = value;375 });376 return row;377}378function selectRowFromCSV (csvConfig, keyValue, logger) {379 const fs = require('fs'),380 Q = require('q'),381 helpers = require('../util/helpers'),382 delimiter = csvConfig.delimiter || ',',383 inputStream = fs.createReadStream(csvConfig.path),384 parser = require('csv-parse')({ delimiter: delimiter }),385 pipe = inputStream.pipe(parser),386 deferred = Q.defer();387 let headers;388 inputStream.on('error', e => {389 logger.error('Cannot read ' + csvConfig.path + ': ' + e);390 deferred.resolve({});391 });392 pipe.on('data', function (rowArray) {393 if (!helpers.defined(headers)) {394 headers = rowArray;395 const keyOnHeader = containsKey(headers, csvConfig.keyColumn);396 if (!keyOnHeader) {397 logger.error('CSV headers "' + headers + '" with delimiter "' + delimiter + '" does not contain keyColumn:"' + csvConfig.keyColumn + '"');398 deferred.resolve({});399 }400 }401 else {402 const row = createRowObject(headers, rowArray);403 if (helpers.defined(row[csvConfig.keyColumn]) && row[csvConfig.keyColumn].localeCompare(keyValue) === 0) {404 deferred.resolve(row);405 }406 }407 });408 pipe.on('error', e => {409 logger.debug('Error: ' + e);410 deferred.resolve({});411 });412 pipe.on('end', () => {413 deferred.resolve({});414 });415 return deferred.promise;416}417function lookupRow (lookupConfig, originalRequest, logger) {418 const Q = require('q'),419 from = getFrom(originalRequest, lookupConfig.key.from),420 fnMap = { regex: regexValue, xpath: xpathValue, jsonpath: jsonpathValue },421 keyValues = fnMap[lookupConfig.key.using.method](from, lookupConfig.key, logger),422 index = lookupConfig.key.index || 0;423 if (lookupConfig.fromDataSource.csv) {424 return selectRowFromCSV(lookupConfig.fromDataSource.csv, keyValues[index], logger);425 }426 else {427 return Q({});428 }429}430function replaceObjectValuesIn (response, token, values, logger) {431 const replacer = field => {432 Object.keys(values).forEach(key => {433 const util = require('util');434 // replace ${TOKEN}["key"] and ${TOKEN}['key'] and ${TOKEN}[key]435 ['"', "'", ''].forEach(function (quoteChar) {436 const quoted = util.format('%s[%s%s%s]', token, quoteChar, key, quoteChar);437 field = globalStringReplace(field, quoted, values[key], logger);438 });439 });440 return field;441 };442 globalObjectReplace(response, replacer);443}444/**445 * Looks up request values from a data source and replaces response tokens with the resulting data446 * @param {Object} originalRequest - The request object447 * @param {Object} responsePromise - The promise returning the response448 * @param {Function} lookupArray - The list of lookup configurations449 * @param {Object} logger - The mountebank logger, useful in debugging450 * @returns {Object}451 */452function lookup (originalRequest, responsePromise, lookupArray, logger) {453 return responsePromise.then(response => {454 const Q = require('q'),455 lookupPromises = lookupArray.map(function (lookupConfig) {456 return lookupRow(lookupConfig, originalRequest, logger).then(function (row) {457 replaceObjectValuesIn(response, lookupConfig.into, row, logger);458 });459 });460 return Q.all(lookupPromises).then(() => Q(response));461 }).catch(error => {462 logger.error(error);463 });464}465/**466 * The entry point to execute all behaviors provided in the API467 * @param {Object} request - The request object468 * @param {Object} response - The response generated from the stubs469 * @param {Object} behaviors - The behaviors specified in the API470 * @param {Object} logger - The mountebank logger, useful for debugging471 * @returns {Object}472 */473function execute (request, response, behaviors, logger) {474 if (!behaviors) {475 return require('q')(response);476 }477 const Q = require('q'),478 combinators = require('../util/combinators'),479 waitFn = behaviors.wait ?480 result => wait(request, result, behaviors.wait, logger) :481 combinators.identity,482 copyFn = behaviors.copy ?483 result => copy(request, result, behaviors.copy, logger) :484 combinators.identity,485 lookupFn = behaviors.lookup ?486 result => lookup(request, result, behaviors.lookup, logger) :487 combinators.identity,488 shellTransformFn = behaviors.shellTransform ?489 result => shellTransform(request, result, behaviors.shellTransform, logger) :490 combinators.identity,491 decorateFn = behaviors.decorate ?492 result => decorate(request, result, behaviors.decorate, logger) :493 combinators.identity;494 logger.debug('using stub response behavior ' + JSON.stringify(behaviors));495 return combinators.compose(decorateFn, shellTransformFn, copyFn, lookupFn, waitFn, Q)(response);496}497module.exports = {498 validate,499 execute: execute...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const mb = require('mountebank');2const imposter = {3 {4 {5 is: {6 }7 }8 }9};10mb.create(imposter).then(() => {11 console.log('Imposter created');12});

Full Screen

Using AI Code Generation

copy

Full Screen

1var mb = require('mountebank');2var options = {3};4mb.create(options, function (error, mb) {5 if (error) {6 console.log('error creating mb', error);7 }8 else {9 console.log('mb created');10 mb.start(function (error) {11 if (error) {12 console.log('error starting mb', error);13 }14 else {15 console.log('mb started');16 mb.post('/imposters', {17 stubs: [{18 responses: [{19 is: {20 }21 }]22 }]23 }, function (error, response) {24 if (error) {25 console.log('error posting stub', error);26 }27 else {28 console.log('stub posted');29 mb.get('/imposters/3000', function (error, response) {30 if (error) {31 console.log('error getting imposters', error);32 }33 else {34 console.log('imposters retrieved', response.body);35 }36 });37 }38 });39 }40 });41 }42});43{ "port": 3000, "protocol": "http", "stubs": [], "numberOfRequests": 0 }44Your name to display (optional):45Your name to display (optional):46mb.get('/imposters/3000/stubs', function (error, response) {47 if (error) {48 console.log('error getting

Full Screen

Using AI Code Generation

copy

Full Screen

1const mb = require('mountebank');2const imposter = mb.create({3 {4 {5 equals: {6 headers: {7 }8 }9 }10 {11 is: {12 }13 }14 }15});16imposter.then(() => {17 console.log('Imposter created');18});19const mb = require('mountebank');20const imposter = mb.create({21 {22 {23 equals: {24 query: {25 }26 }27 }28 {29 is: {30 }31 }32 }33});34imposter.then(() => {35 console.log('Imposter created');36});37const mb = require('mountebank');38const imposter = mb.create({39 {40 {41 equals: {42 body: {43 }44 }45 }46 {47 is: {48 }49 }50 }51});52imposter.then(() => {53 console.log('Imposter created');54});55const mb = require('mountebank');56const imposter = mb.create({

Full Screen

Using AI Code Generation

copy

Full Screen

1const imposter = {2 stubs: [{3 predicates: [{4 equals: {5 }6 }],7 responses: [{8 is: {9 }10 }]11 }]12};13const mb = require('mountebank');14mb.create(imposter).then(function (api) {15 api.get('/imposters').then(function (response) {16 console.log(JSON.stringify(response.body, null, 2));17 });18});19const mb = require('mountebank');20 console.log(response.body);21});22const mb = require('mountebank');23mb.create(8080).then(function (api) {24 api.get('/imposters').then(function (response) {25 console.log(JSON.stringify(response.body, null, 2));26 });27});

Full Screen

Using AI Code Generation

copy

Full Screen

1const imposter = { protocol: 'http', port: 3000 };2const stub = {3 {4 is: {5 headers: { 'Content-Type': 'application/json' },6 body: { message: 'Hello World' }7 }8 }9};10const mb = require('mountebank');11mb.create({ port: 2525, pidfile: 'mb.pid', logfile: 'mb.log' }, () => {12 mb.post('/imposters', imposter, () => {13 mb.post(`/imposters/${imposter.port}/stubs`, stub, () => {14 mb.stop(() => {15 });16 });17 });18});19const imposter = { protocol: 'http', port: 3000 };20const stub = {21 {22 is: {23 headers: { 'Content-Type': 'application/json' },24 body: { message: 'Hello World' }25 }26 }27};28const mb = require('mountebank');29mb.create({ port: 2525, pidfile: 'mb.pid', logfile: 'mb.log' }, () => {30 mb.post('/imposters', imposter, () => {31 mb.post(`/imposters/${imposter.port}/stubs`, stub, () => {32 mb.stop(() => {33 });34 });35 });36});37const imposter = { protocol: 'http', port: 3000 };38const stub = {39 {40 is: {41 headers: { 'Content-Type': 'application/json' },42 body: { message: 'Hello World' }43 }44 }45};46const mb = require('mountebank');47mb.create({ port: 2525, pidfile: 'mb.pid', logfile: 'mb.log' }, () => {48 mb.post('/imposters', imposter, () => {49 mb.post(`/imposters/${imposter.port}/stubs

Full Screen

Using AI Code Generation

copy

Full Screen

1var mb = require('mountebank');2mb.keyOnHeader('X-User-Id');3mb.create({4'stubs': [{5'predicates': [{6'equals': {7'headers': {8}9}10}],11'responses': [{12'is': {13'headers': {14},15'body': '{"message": "Hello World"}'16}17}]18}]19});20mb.create({21'stubs': [{22'predicates': [{23'equals': {24'headers': {25}26}27}],28'responses': [{29'is': {30'headers': {31},32'body': '{"message": "Hello World"}'33}34}]35}]36});37var mb = require('mountebank');38mb.keyOnHeader('X-User-Id');39mb.create({40'stubs': [{41'predicates': [{42'equals': {

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run mountebank automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful