bbyars/mountebank

View on GitHub
src/views/docs/api/behaviors/decorate.ejs

Summary

Maintainability
Test Coverage
<table>
  <tr>
    <th>Parameter</th>
    <th>Type</th>
    <th>Description</th>
  </tr>
  <tr>
    <td><code>decorate</code></td>
    <td>A string</td>
    <td>The <code>decorate</code> function, used to transform the response through JavaScript. It can either
    mutate the response in place or return a new response object.

    <p class='warning-icon'>The <code><a href='/docs/commandLine'>--allowInjection</a></code> command
      line flag must be set to support this behavior.</p>
    </td>
  </tr>
</table>

<p>The <code>decorate</code> function should take a single parameter, which will contain the following fields:</p>

<table>
    <tr>
        <th>Field</th>
        <th>Description</th>
    </tr>
    <tr>
        <td><code>request</code></td>
        <td>The entire request object, containing all request fields</td>
    </tr>
    <tr>
        <td><code>response</code></td>
        <td>The entire response object</td>
    </tr>
    <tr>
        <td><code>state</code></td>
        <td>An initially empty object, scoped to the imposter, that will be shared with
        <a href='/docs/api/injection#predicate-injection'>predicate</a> and
        <a href='/docs/api/injection#response-injection'>response injection</a> functions.
        You can use it to capture and mutate shared state.</td>
    </tr>
    <tr>
        <td><code>logger</code></td>
        <td>A logger object with <code>debug</code>, <code>info</code>, <code>warn</code>,
        and <code>error</code> functions to write to the mountebank logs.</td>
    </tr>
</table>

<p>The <code>decorate</code> behavior is quite powerful, allowing nearly unlimited (synchronous) post-processing
of the response.  Since it relies on JavaScript injection, the <a href='/docs/commandLine'>--allowInjection</a>
flag must be passed in to <code>mb</code> on startup.</p>

<p>Here are a couple ideas of what to do with post-processing:</p>

<ul class='bullet-list'>
  <li><a href='#add-timestamp'>Add the current time to a response</a></li>
  <li><a href='#add-custom-header'>Add a custom header to a proxied response</a></li>
</ul>

<h3 id='add-timestamp'>Add the current time to a response</h3>

<p>Many people store static imposter files and load them via the <a href='/docs/commandLine'>--configfile</a>
command line switch.  The <code>decorate</code> behavior supports an elegant way of adding dynamic data
to the responses.  Let's add the current timestamp to each response.  We'll pass in a stringified version
of the following JavaScript function:</p>

<testScenario name='decorate'>
<pre><code>(config) => {
    var pad = function (number) {
            return (number &lt; 10) ? '0' + number : number.toString();
        },
        now = new Date(),
        time = pad(now.getHours()) + ':' + pad(now.getMinutes()) + ':' + pad(now.getSeconds());

    config.response.body = config.response.body.replace('${TIME}', time);
}</code></pre>

    <step type='http'>
<pre><code>POST /imposters HTTP/1.1
Host: localhost:<%= port %>
Accept: application/json
Content-Type: application/json

{
  "port": 5545,
  "protocol": "http",
  "stubs": [
    {
      "responses": [
        {
          "is": {
            "body": "The time is <strong class='highlight1'>${TIME}</strong>"
          },
          "behaviors": [
            { "decorate": "(config) => { var pad = function (number) { return (number &lt; 10) ? '0' + number : number.toString(); }, now = new Date(), time = pad(now.getHours()) + ':' + pad(now.getMinutes()) + ':' + pad(now.getSeconds()); config.response.body = config.response.body.replace('${TIME}', time); }" }
          ]
        }
      ]
    }
  ]
}</code></pre>
    </step>

<p>Now we can call the imposter to get the current time.</p>

    <step type='http'>
<pre><code>GET / HTTP/1.1
Host: localhost:5545</code></pre>

        <assertResponse>
<pre><code>HTTP/1.1 200 OK
Connection: close
Date: <volatile>Thu, 01 Jan 2015 02:30:31 GMT</volatile>
Transfer-Encoding: chunked

The time is <volatile><strong class='highlight1'>16:43:02</strong></volatile></code></pre>
        </assertResponse>
    </step>

<h3 id='add-custom-header'>Add a custom header to a proxied response</h3>

<p><a href='/docs/api/proxies'>Proxying</a> provides considerable power out of the box.  However,
there are times where you need to augment the proxied response with something else to properly
simulate your testing scenario.  In this example, we'll proxy to the
<a href='#add-timestamp'>example above</a> (port 5545) that adds the current time to the response body.
We'll augment the proxied response with a custom header.  Here's the decorator function, passed
into the imposter creation as a string:</p>

<pre><code>(config) => {
    config.response.headers['X-Test'] = 'True';
}</code></pre>

    <step type='http'>
<pre><code>POST /imposters HTTP/1.1
Host: localhost:<%= port %>
Accept: application/json
Content-Type: application/json

{
  "port": 7545,
  "protocol": "http",
  "stubs": [
    {
      "responses": [
        {
          "proxy": { "to": "http://localhost:5545" },
          "behaviors": [
            { "decorate": "(config) => { <strong class='highlight1'>config.response.headers['X-Test'] = 'True';</strong> }" }
          ]
        }
      ]
    }
  ]
}</code></pre>
    </step>

<p>Now we should get the custom header back:</p>

    <step type='http'>
<pre><code>GET /test HTTP/1.1
Host: localhost:7545</code></pre>

        <assertResponse>
<pre><code>HTTP/1.1 200 OK
Connection: close
Date: <volatile>Thu, 01 Jan 2015 02:30:31 GMT</volatile>
Transfer-Encoding: chunked
<strong class='highlight1'>X-Test: True</strong>

The time is <volatile>17:16:23</volatile></code></pre>
        </assertResponse>
    </step>

    <step type='http'>
<code class='hidden'>DELETE /imposters/5545 HTTP/1.1
Host: localhost:<%= port %></code>
    </step>

    <step type='http'>
<code class='hidden'>DELETE /imposters/7545 HTTP/1.1
Host: localhost:<%= port %></code>
    </step>
</testScenario>