Node's Pretty Magical

    dynamock

    1.2.0 • Public • Published

    dynamock

    npm version David node Build Status Coverage Status

    dynamock is a dynamic mock/fixture HTTP server designed for functional testing.

    Installation

    yarn add dynamock -D
    # or NPM
    npm install dynamock --save-dev

    Usage

    ⚠️ Security

    Be aware of running your dynamock server in a CLOSED network, there is no authentication required to configure it.
    It is highly recommended using dynamock for dev/testing purpose ONLY.

    Run the server (NodeJS required)

    # dynamock PORT [HOST]
    dynamock 3001

    Inject fixtures

    fetch('http://localhost:3001/___fixtures', {
      method: 'POST',
      body: {
        request: {
          method: 'GET',
          path: '/products/1'
        },
        response: {
          body: {
            id: 1
          }
        }
      }
    })

    Consume fixtures

    fetch('http://localhost:3001/products/1', { method: 'GET' })
      .then(response => response.json())
      .then(response => assert.equal(response, { id: 1 }))

    Dynamock is designed to remove the fixture once consumed, see options.lifetime to adapt this behavior.

    fetch('http://localhost:3001/products/1', { method: 'GET' }).then(response => assert.equal(response.status, 404))

    Property response matching

    By default, dynamock uses partial matching for headers, query and cookies.

    Configuration api

    Using the configuration is optional. However, it gives the ability of reusing redundant data across requests and simplifying fixtures setup.

    GET /___config - Retrieve configuration

    Responses

    • Status 200 - OK
    {
      "cors": "{null|'*'} - '*' allows all requests via cors headers, this creates a global route OPTIONS",
      "headers": "{object} - Dictionary of headers (object) by name (string)",
      "query": "{object} - Dictionary of query (object) by name (string)",
      "cookies": "{object} - Dictionary of cookies (object) by name (string)"
    }

    Example:

    {
      "cors": null,
      "headers": {},
      "query": {},
      "cookies": {}
    }

    PUT /___config - Update configuration

    Request

    • Body
    {
      "cors": "{null|'*'} [default=null] - '*' allows all requests via cors headers, this creates a global route OPTIONS",
      "headers": "{object} [default={}] - Dictionary of headers (object) by name (string)",
      "query": "{object} [default={}] - Dictionary of query (object) by name (string)",
      "cookies": "{object} [default={}] - Dictionary of cookies (object) by name (string)"
    }

    Example:

    {
      "cors": "*",
      "headers": {
        "apiBearer": {
          "Authorization": "Bearer xyz"
        }
      }
    }

    Responses

    • Status 200 - OK
    {
      "cors": "{null|'*'}",
      "headers": "{object}",
      "query": "{object}",
      "cookies": "{object}"
    }

    Example:

    {
      "cors": null,
      "headers": {
        "captcha": {
          "X-CAPTCHA-TOKEN": "fake"
        },
        "cors": {
          "Access-Control-Allow-Origin": "*",
          "Access-Control-Allow-Methods": "*",
          "Access-Control-Allow-Headers": "*"
        }
      },
      "query": {
        "campaign": {
          "utm_source": "x",
          "utm_campaign": "y"
        }
      },
      "cookies": {
        "anonymousUser": {
          "PHPSESSID": "x"
        },
        "loggedInUser": {
          "PHPSESSID": "y"
        }
      }
    }
    • Status 400 - BAD REQUEST
    Wrong configuration format
    

    DELETE /___config - Reset configuration

    Responses

    • Status 204 - NO CONTENT

    Fixtures api

    A fixture is composed of:

    • request data to match the incoming requests
    • response data to define the result(s) of the requests

    POST /___fixtures - Add fixture

    Request

    • Body
    {
      "request": {
        "method": "{string} - Http method to match requests, case insensitive, use wildcard '*' to match all",
        "path": "{string} - Http path to match requests, use wildcard '*' to match all",
        "headers": "{object|array} [default={}] - Headers to match requests",
        "query": "{object|array} [default={}] - Query to match requests",
        "cookies": "{object|array} [default={}] - Cookies to match requests",
        "body": "{object} [default=``] - Body to match requests",
        "options": {
          "path": {
            "allowRegex": "{boolean} [default=false] - Allow matching RegExp"
          },
          "method": {
            "allowRegex": "{boolean} [default=false] - Allow matching RegExp"
          },
          "headers": {
            "strict": "{boolean} [default=false] - Strictly match headers",
            "allowRegex": "{boolean} [default=false] - Allow matching RegExp"
          },
          "cookies": {
            "strict": "{boolean} [default=false] - Strictly match cookies",
            "allowRegex": "{boolean} [default=false] - Allow matching RegExp"
          },
          "query": {
            "strict": "{boolean} [default=false] - Strictly match query",
            "allowRegex": "{boolean} [default=false] - Allow matching RegExp"
          },
          "body": {
            "strict": "{boolean} [default=false] - Strictly match body",
            "allowRegex": "{boolean} [default=false] - Allow matching RegExp"
          }
        }
      },
      "response": {
        "status": "{number} [default=200] - Response status code",
        "headers": "{object|array} [default={}] - Response headers",
        "cookies": "{object|array} [default={}] - Response cookies",
        "body": "{string|object|array} [default=``] - Body to response",
        "filepath": "{string} [default=``] - Absolute filepath to serve with auto mime-types",
        "options": {
          "delay": "{number} [default=0] - Delay the response with a number of milliseconds",
          "lifetime": "{number} [default=1] - Number of times the fixture can be consumed before getting removed, use 0 for unlimited consumption"
        }
      },
      "responses": "{array} [default=[]] - Array of responses"
    }

    Examples:

    {
      "request": {
        "method": "GET",
        "path": "/pandas"
      },
      "response": {
        "body": [{ "id": "1" }, { "id": "2" }]
      }
    }
    {
      "request": {
        "method": "GET",
        "path": "/cdn/images/fennec.jpg"
      },
      "response": {
        "filepath": "/absolute/path/tofennec.jpg",
        "options": {
          "delay": 1000
        }
      }
    }
    {
      "request": {
        "method": "POST",
        "path": "/heros",
        "body": {
          "name": "po",
          "type": "panda"
        },
        "options": {
          "body": {
            "strict": true
          }
        }
      },
      "response": {
        "body": {
          "id": "1",
          "name": "po",
          "type": "panda"
        }
      }
    }
    {
      "request": {
        "method": "OPTIONS",
        "path": "*"
      },
      "response": {
        "headers": {
          "Access-Control-Allow-Origin": "*",
          "Access-Control-Allow-Methods": "*",
          "Access-Control-Allow-Headers": "*"
        },
        "body": ""
      }
    }
    {
      "request": {
        "method": "get",
        "path": "/"
      },
      "responses": [
        {
          "body": "first return"
        },
        {
          "body": "second return"
        }
      ]
    }
    {
      "request": {
        "method": "GET",
        "path": "/",
        "headers": {
          "user-agent": "/firefox/70$/i"
        },
        "options": {
          "headers": {
            "allowRegex": true
          }
        }
      },
      "response": {
        "body": "Only for Firefox 70 users !"
      }
    }

    Responses

    • Status 200 - OK
    {
      "id": "{string}"
    }

    Example:

    {
      "id": "38ed32e9fb0a1e5c7cb1b6f0ff43f6060d8b4508"
    }
    • Status 400 - BAD REQUEST

    The configuration is not valid

    • Status 409 - CONFLICT
    Route {METHOD} ${PATH} is already registered.
    

    POST /___fixtures/bulk - Bulk add fixtures

    It is meant to setup multiple fixtures at once.

    Request

    • Body
    [
      {
        "request": {
          "method": "{string} - Http method to match requests, case insensitive, use wildcard '*' to match all",
          "path": "{string} - Http path to match requests, use wildcard '*' to match all",
          "headers": "{object|array} [default={}] - Headers to match requests",
          "query": "{object|array} [default={}] - Query to match requests",
          "cookies": "{object|array} [default={}] - Cookies to match requests",
          "body": "{object} [default=``] - Body to match requests",
          "options": {
            "path": {
              "allowRegex": "{boolean} [default=false] - Allow matching RegExp"
            },
            "method": {
              "allowRegex": "{boolean} [default=false] - Allow matching RegExp"
            },
            "headers": {
              "strict": "{boolean} [default=false] - Strictly match headers",
              "allowRegex": "{boolean} [default=false] - Allow matching RegExp"
            },
            "cookies": {
              "strict": "{boolean} [default=false] - Strictly match cookies",
              "allowRegex": "{boolean} [default=false] - Allow matching RegExp"
            },
            "query": {
              "strict": "{boolean} [default=false] - Strictly match query",
              "allowRegex": "{boolean} [default=false] - Allow matching RegExp"
            },
            "body": {
              "strict": "{boolean} [default=false] - Strictly match body",
              "allowRegex": "{boolean} [default=false] - Allow matching RegExp"
            }
          }
        },
        "response": {
          "status": "{number} [default=200] - Response status code",
          "headers": "{object|array} [default={}] - Response headers",
          "cookies": "{object|array} [default={}] - Response cookies",
          "body": "{string|object|array} [default=``] - Body response",
          "filepath": "{string} [default=``] - Absolute filepath to serve with auto mime-types",
          "options": {
            "delay": "{number} [default=0] - Delay the response with a number of milliseconds",
            "lifetime": "{number} [default=1] - Number of times the fixture can be consumed before getting removed, use 0 for unlimited consumption"
          }
        },
        "responses": "{array} [default=[]] - Array of responses"
      }
    ]

    Examples:

    [
      {
        "request": {
          "method": "GET",
          "path": "/pandas"
        },
        "response": {
          "body": [{ "id": "1" }, { "id": "2" }]
        }
      },
      {
        "request": {
          "method": "GET",
          "path": "/cdn/images/fennec.jpg"
        },
        "response": {
          "filepath": "/absolute/path/tofennec.jpg"
        }
      }
    ]

    Responses

    • Status 200 - OK
    [
      {
        "id": "{string}"
      }
    ]

    Example:

    [
      {
        "id": "38ed32e9fb0a1e5c7cb1b6f0ff43f6060d8b4508"
      },
      {
        "id": "086c67ef89fd832deeae33b209e6e8ecc6b32003"
      }
    ]
    • Status 400 - BAD REQUEST

    The fixture is not valid

    • Status 409 - CONFLICT

    Another fixture with the same request is already registered


    DELETE /___fixtures/:id - Delete a fixture

    Request

    • Params
    {
      "id": "{string}"
    }

    Example:

        DELETE /___fixtures/38ed32e9fb0a1e5c7cb1b6f0ff43f6060d8b4508
    

    Responses

    • Status 204 - NO CONTENT

    DELETE /___fixtures - Delete all fixtures

    Responses

    • Status 204 - NO CONTENT

    Next features

    • Handle other web protocols like https or websocket
    • Security tokens for public environments

    Install

    npm i dynamock

    DownloadsWeekly Downloads

    4

    Version

    1.2.0

    License

    MIT

    Unpacked Size

    29.1 kB

    Total Files

    8

    Last publish

    Collaborators

    • devside