Coder Social home page Coder Social logo

parrot's Introduction

Parrot

Parrot is a set of tools that allow you to create HTTP mocks and organize them into scenarios in order to develop your app against different sets of data. We have implemented all of Parrot's functionality in JavaScript, but scenarios are a general specification that can be implemented in any language.

👩‍💻 Hiring 👨‍💻

Want to get paid for your contributions to parrot?

Send your resume to [email protected]

🤹‍ Usage

Let's walk through a common development workflow using Parrot.

Define your scenarios

import { describe, it, get, post, graphql } from 'parrot-friendly';
import casual from 'casual'; // for generating fake data
import schema from './schema'; // our GraphQL schema

const scenarios = describe('Ship Log', () => {
  it('has a ship log', () => {
    // respond with a mock JSON file and add a delay
    get('/ship_log')
      .response(require('./mocks/shipLog.json'))
      .delay(1200);

    // respond with the request body that was sent
    post('/ship_log').response(req => req.body);
  });

  it('has a random ship log', () => {
    // respond with random data generated by casual
    get('/ship_log').response(() => [
      {
        port: casual.city,
        captain: casual.full_name,
      },
    ]);
  });

  it('has a server error', () => {
    // respond with a 500 status
    get('/ship_log').status(500);
  });

  it('has a ship log from GraphQL', () => {
    // respond to GraphQL queries
    graphql('/graphql', schema, () => ({
      ShipLog: () => require('./mocks/shipLog.json'),
    }));
  });
});

export default scenarios;

More information about writing scenarios can be found in the scenarios documentation.

Add them to your server

import express from 'express';
import parrot from 'parrot-middleware';
import scenarios from './scenarios';

const app = express();
app.use(parrot(scenarios));
app.listen(3000);

Develop with Parrot's devtools

parrot-devtools

Example API requests

Fetch current scenario.

$ curl 'http://localhost:3002/parrot/scenario'

Fetch all scenarios.

$ curl 'http://localhost:3002/parrot/scenarios'

Setting parrot to a new scenario.

$ curl -X POST -H "Content-Type: application/json" -d '{ "scenario": "[scenario name here]" }'  'http://localhost:3002/parrot/scenario'

📦 Packages

Parrot is divided into several packages that can be used together depending on your use case.

Name Description
parrot-core Core Parrot functionality that can be extended to new use cases
parrot-devtools Devtools that allow you to switch between Parrot scenarios
parrot-fetch Fetch mocking implementation of Parrot
parrot-friendly Helper library to write your scenarios in BDD style
parrot-graphql Helper library to add GraphQL mocks to your scenarios
parrot-middleware Express middleware implementation of Parrot
parrot-server CLI to get a parrot server up and running

🏆 Contributing

We welcome Your interest in the American Express Open Source Community on Github. Any Contributor to any Open Source Project managed by the American Express Open Source Community must accept and sign an Agreement indicating agreement to the terms below. Except for the rights granted in this Agreement to American Express and to recipients of software distributed by American Express, You reserve all right, title, and interest, if any, in and to Your Contributions. Please fill out the Agreement.

Please see our CONTRIBUTING.md.

🗝️ License

Any contributions made under this project will be governed by the Apache License 2.0.

🗣️ Code of Conduct

This project adheres to the American Express Community Guidelines. By participating, you are expected to honor these guidelines.

parrot's People

Contributors

amexjake avatar anescobar1991 avatar dependabot[bot] avatar dsope05 avatar ferrettin avatar francois-esquire avatar jackjocross avatar jadshead avatar jsmartfo avatar matthew-mallimo avatar maxb08 avatar michael-macal avatar narmeennaveedahmed avatar nellyk avatar pixnbits avatar shivaylamba avatar smackfu avatar tklever avatar yono38 avatar zleight1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

parrot's Issues

Enable websocket scenarios

I want to add parrot-websockets so that developers can mock scenarios using WebSockets.

Usage

// scenarios.js

module.exports.httpScenarios = { ... };

module.exports.wssScenarios = {
  'some websocket': [
    {
      on: 'message',
      emmit: {
        event: 'message',
        args: {
          foo: 'foo',
          bar: 'bar',
        },
      },
    },
  ],
};
// dev.middleware.js

const parrot = require('parrot-middleware');
const parrotWs = require('parrot-websockets');
const { httpScenarios, wssScenarios } = require('./mock/scenarios');

module.exports = (app) => {
  app.use(parrot(httpScenarios));
  app.use(parrotWs(wssScenarios));
};

parrot: Enhance pirate-ship-app example

I want to enhance the pirate-ship-app example to include more examples of parrot's capabilities.

These examples may include:

  • query string matching
  • POST/PUT scenarios
  • URI matching

Additionally, the example app should be clearly called out in the README for better visibility. This should include instructions on starting the app.

getParams from parrot-core should be exposed

Given a somewhat complex matcher like this:

  const getBook = ({ url }, match) => {
    const path = '/books/:bookId';
    if (match({ path, method: 'GET' })) {
      const { bookId } = getParams(url, path);
      const book = books.find((book) => book.bookId === bookId);
      if (!book) {
        return { status: 404 };
      }
      return { status: 200, body: book };
    }
    return null;
  };

The getParams function that is needed is not exposed by parrot, even though it has an implementation.

It would be convenient if that was available for consumers to use.

Add ability to use function for status

For more complex mocks, parrot supports passing a function as the body, which can be matched against the request object to return different responses.

See: https://github.com/americanexpress/parrot/blob/main/packages/parrot-core/src/utils/resolveResponse.js#L31

There are use-cases where it would be convenient to return a different http status code for different requests to the same endpoint.

Currently the status field does not support being passed a function:

RangeError [ERR_HTTP_INVALID_STATUS_CODE]: Invalid status code: () => 200
    at ServerResponse.writeHead (_http_server.js:248:11)
    at ServerResponse._implicitHeader (_http_server.js:239:8)
    at write_ (_http_outgoing.js:654:9)
    at ServerResponse.end (_http_outgoing.js:766:5)

Testing lockout scenario

I have a scenario where I have to call an API multiple times until it sends a locked out response. Is there is a way to achieve this in parrot? I tried this code, but it did not work. It always gives the first response 1001.

[{
      request: {
        path: '/test',
        method: 'POST',
      },
      response: {
        body: {
          message: 'Failed First attempt',
          code: 1001,
        },
        status: 400,
      },
    },
    {
      request: {
        path: '/test',
        method: 'POST',
      },
      response: {
        body: {
          message: 'Failed Second attempt',
          code: 1002,
        },
        status: 400,
      },
    },
    {
      request: {
        path: '/test',
        method: 'POST',
      },
      response: {
        body: {
          message: 'Locked out',
          code: 1003,
        },
        status: 400,
      },
    }]

Middleware URL does not accept http://localhost:3002/ only accepts http://localhost:3002

All mocks were served correctly as I was able to see the proper response at http://localhost:3002/parrot/scenario; however, Parrot Devtools was showing me the error message:

Failed to Load Scenarios
Try refreshing or updating the middleware URL in settings.

The middleware URL should be able to accept http://localhost:3002/ and http://localhost:3002 as acceptable URLs.

Reporting a vulnerability

Hello!

I hope you are doing well!

We are a security research team. Our tool automatically detected a vulnerability in this repository. We want to disclose it responsibly. GitHub has a feature called Private vulnerability reporting, which enables security research to privately disclose a vulnerability. Unfortunately, it is not enabled for this repository.

Can you enable it, so that we can report it?

Thanks in advance!

PS: you can read about how to enable private vulnerability reporting here: https://docs.github.com/en/code-security/security-advisories/repository-security-advisories/configuring-private-vulnerability-reporting-for-a-repository

New branding for Parrot README

Add new branding to all packages in the project

  • parrot
  • parrot-core
  • parrot-devtools
  • parrot-fetch
  • parrot-friendly
  • parrot-graphql
  • parrot-middleware
  • parrot-server

Add Partial Success (Data & Error) to graphql response

Similar to #100 we'd like to add an enhancement to Parrot responses.

At the moment, there is no option to add both data and error objects outside of the body. We'd like to add to support partial success graphql responses. See example. I want to make sure this is compatible with the parrot-friendly formatting of the scenarios so I think we should update the scenarios file to use or add a second example app

{
  "data": {
    "getInt": 12,
    "getString": null
  },
  "errors": [
    {
      "message": "Failed to get string!"
      // ...additional fields...
    }
  ]
}

Here is my WIP forked repo & branch

Note: to test this locally I needed to link parrot-friendly to the local version with “parrot-friendly”: “file:../../packages/parrot-friendly”,, if the parrot-friendly changes need to be approved & merged first I can remove the friendly-pirate-app changes and include those in a separate followup PR

Unclear Example Name

I wanted to start by saying congratulations on open sourcing this Amex team!

I think it would be nice to have a clearer name for the example application than create-react-app. Something like ship-example-app. This would make it more distinctive if others want to contribute additional examples in the future.

Add a CLI version of Parrot

It would be nice to have a CLI tool that starts a server running parrot-middleware. This would reduce the setup work needed to start using Parrot.

Failing test cases

` FAIL packages/parrot-server/tests/index.spec.js
● defaults to port 3001 if --port is not given

expect(received).toBe(expected) // Object.is equality

Expected: 200
Received: 404

  53 | 
  54 |   const response = await fetch('http://localhost:3001/parrot/scenarios');
> 55 |   expect(response.status).toBe(200);
     |                           ^
  56 | });
  57 | 
  58 | it('starts server on given port', async () => {

  at _callee2$ (packages/parrot-server/__tests__/index.spec.js:55:27)
  at tryCatch (node_modules/regenerator-runtime/runtime.js:45:40)
  at Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:271:22)
  at Generator.prototype.(anonymous function) [as next] (node_modules/regenerator-runtime/runtime.js:97:21)
  at asyncGeneratorStep (packages/parrot-server/__tests__/index.spec.js:11:103)
  at _next (packages/parrot-server/__tests__/index.spec.js:13:194)

● starts server on given port

expect(received).toBe(expected) // Object.is equality

Expected: 200
Received: 404

  66 | 
  67 |   const response = await fetch(`http://localhost:${portNumber}/parrot/scenarios`);
> 68 |   expect(response.status).toBe(200);
     |                           ^
  69 | });
  70 | 
  71 | it('exits with status 1 if something goes wrong while starting the server', () => {

  at _callee3$ (packages/parrot-server/__tests__/index.spec.js:68:27)
  at tryCatch (node_modules/regenerator-runtime/runtime.js:45:40)
  at Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:271:22)
  at Generator.prototype.(anonymous function) [as next] (node_modules/regenerator-runtime/runtime.js:97:21)
  at asyncGeneratorStep (packages/parrot-server/__tests__/index.spec.js:11:103)
  at _next (packages/parrot-server/__tests__/index.spec.js:13:194)

`

Parrot Dev Tool Firefox

Unable to install Parrot dev tool in Firefox. It is throwing error "Add on is corrupted" while trying to install

Parrot extension disappears

I unfortunately don't know what causes this, and I haven't been able to recreate it, however I used to have the Parrot extension added to my Chrome browser, and it was showing in my list of extensions.

However, when I opened up the Chrome dev tools, I couldn't see the Parrot tab. After rebooting, I went into the Chrome extensions section and found that the extension had disappeared. I think perhaps it uninstalled itself? It may occur when Chrome updates itself, but this is purely a guess.

Project Alive and Well!

We've recently been looking for scenario based mocking tools and came across Parrot. I notice there have been very few commits and no activity for the better part of a year.

Was wondering if this project has been abandoned or is still in use. Surprisingly there hasn't been a lot of options in the mock scenario space and Parrot seems to be the closest to what our team has been looking for.

Is Parrot still being used internally? Is there any hope for continued development?

Sync project with internal repo

This project has become out of sync with our internal repository. We will need to force push any updates to this project and release a breaking change.

Parrot Devtools crashes when selecting scenario while using One App

When using parrot-graphql on a One App module, selecting the scenario crashed my One App server with the below error. Let me know if you need any other info.

When the server restarted, it was using my scenario without issues.

TypeError: Cannot read property 'length' of undefined
    at matchMock (/opt/module-workspace/module/node_modules/parrot-core/lib/utils/matchMock.js:56:37)
    at _callee$ (/opt/module-workspace/module/node_modules/parrot-core/lib/Parrot.js:90:41)
    at tryCatch (/opt/module-workspace/module/node_modules/regenerator-runtime/runtime.js:63:40)
    at Generator.invoke [as _invoke] (/opt/module-workspace/module/node_modules/regenerator-runtime/runtime.js:293:22)
    at Generator.next (/opt/module-workspace/module/node_modules/regenerator-runtime/runtime.js:118:21)
    at asyncGeneratorStep (/opt/module-workspace/module/node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24)
    at _next (/opt/module-workspace/module/node_modules/@babel/runtime/helpers/asyncToGenerator.js:25:9)
    at /opt/module-workspace/module/node_modules/@babel/runtime/helpers/asyncToGenerator.js:32:7
    at new Promise (<anonymous>)
    at /opt/module-workspace/module/node_modules/@babel/runtime/helpers/asyncToGenerator.js:21:12

parrot-graphql isn't transpiled properly

It looks like the parrot-graphql package is missing a .babelrc because the generated code is es6 with imports and fails in a node environment.

import { mockServer } from 'graphql-tools';
       ^
SyntaxError: Unexpected token {
    at Module._compile (internal/modules/cjs/loader.js:723:23)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Module.require (internal/modules/cjs/loader.js:692:17)
    at require (internal/modules/cjs/helpers.js:25:18)
    at Object.<anonymous> (C:\Users\zachary\Documents\Git\TipaltiGit\PayerDashboardAngular\Scripts\app\node_modules\parrot-friendly\lib\index.js:13:45)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)

To reproduce, just try and require it in a node file and run node ./file.js;

parrot-devtools: Chrome extension screenshots

Chrome Web Store requires 1280x800 pixel screenshots when publishing an extension.

I'd like to use the gif currently displayed in the readme but it does not meet the size requirements.

We need to recapture the shots used in the gif and reformat with the correct dimensions.

Add contributing guidelines

I want to add a CONTRIBUTING.md file to document how to contribute to this project.

File should include how to create a new lerna release.

parrot-devtools: Searchbar

A simple searchbar that filters the scenarios shown in the scenario list. I have an MVP built out that filters as you type and looks like images shown below. The scenario name has to include the input string to be shown. I'm thinking about moving the input field to the top, above the scenario list but let me know if anyone has any preferences on that.

Screen Shot 2020-05-06 at 4 20 23 PM Screen Shot 2020-05-06 at 4 18 45 PM

Default exports are broken?

When parrot-middleware is being used with Typescript, the default import statement for parrot-middleware fails:

import parrot from 'parrot-middleware'
TypeError: parrot_middleware_1.default is not a function

It seems as though the problem may be with how the default package is being exported here:
https://unpkg.com/[email protected]/lib/index.js.

The following line:

module.exports = exports['default'];

may be causing issues because module.exports is expecting something with the following shape for default exports:

module.exports = { default: ... }

The workaround is currently:

import * as parrot from 'parrot-middleware'

Improved scenario organization (backwards compatible parrot-friendly enhancement)

Issue

A single list is sufficient when we have limited scenarios, but we're finding we have too many scenarios and it can be difficult to find the one you need. We have multiple locales, audiences, products & api responses that we need to mock, which results in a long list with redundant keywords in the title

Examples

Here is an example of the default view of scenarios vs how long a hidden list can be
image

Proposed Solutions

I would like to start a discussion around this topic to find the easiest way to add some additional organization. Here are some Ideas I had (including very quick sketchy mock ups just to illustrate the idea)

  1. Folders or Drawers - Each describe in the parrot-friendly syntax would act as a folder or layer of organization, and each it would act as the scenario. For the example above you could have something like Locale > Single / Multi > Scenario
image image
  1. Tags or Labels - Each it could accept an optional array of 'tags' to be applied to the scenario.
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.