npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

dynamock

v2.1.1

Published

Dynamic mock server which serves fixtures based on property matching

Downloads

3,382

Readme

dynamock

npm version 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',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    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.

/___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": {}
}

/___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

/___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

/___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",
        "disableEncodeURI": "{boolean} [default=false] - Disable encode URI, always on when allowRegex is true"
      },
      "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 !"
  }
}
{
  "request": {
    "method": "GET",
    "path": "/%20a",
    "options": {
      "path": {
        "disableEncodeURI": true
      }
    }
  },
  "response": {
    "body": "This will match '/ a' or '/%20a' calls"
  }
}

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.

/___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

/___fixtures/:id - Delete a fixture

Request

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

Example:

    DELETE /___fixtures/38ed32e9fb0a1e5c7cb1b6f0ff43f6060d8b4508

Responses

  • Status 204 - NO CONTENT

/___fixtures - Delete all fixtures

Responses

  • Status 204 - NO CONTENT

Next features

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