Coder Social home page Coder Social logo

netflix / pollyjs Goto Github PK

View Code? Open in Web Editor NEW
10.2K 370.0 352.0 4.74 MB

Record, Replay, and Stub HTTP Interactions.

Home Page: https://netflix.github.io/pollyjs

License: Apache License 2.0

JavaScript 98.65% HTML 0.57% Shell 0.39% Handlebars 0.02% Mustache 0.37%
javascript browser nodejs testing netflix record replay

pollyjs's Introduction

Polly.JS

Record, Replay, and Stub HTTP Interactions

Build Status license

Polly.JS is a standalone, framework-agnostic JavaScript library that enables recording, replaying, and stubbing of HTTP interactions. By tapping into multiple request APIs across both Node & the browser, Polly.JS is able to mock requests and responses with little to no configuration while giving you the ability to take full control of each request with a simple, powerful, and intuitive API.

Interested in contributing or just seeing Polly in action? Head over to CONTRIBUTING.md to learn how to spin up the project!

Why Polly?

Keeping fixtures and factories in parity with your APIs can be a time consuming process. Polly alleviates this process by recording and maintaining actual server responses while also staying flexible.

  • Record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests.
  • Use Polly's client-side server to modify or intercept requests and responses to simulate different application states (e.g. loading, error, etc.).

Features

  • ๐Ÿš€ Node & Browser Support
  • โšก๏ธ๏ธ Simple, Powerful, & Intuitive API
  • ๐Ÿ’Ž First Class Mocha & QUnit Test Helpers
  • ๐Ÿ”ฅ Intercept, Pass-Through, and Attach Events
  • ๐Ÿ“ผ Record to Disk or Local Storage
  • โฑ Slow Down or Speed Up Time

Getting Started

Check out the Quick Start documentation to get started.

Usage

Let's take a look at what an example test case would look like using Polly.

import { Polly } from '@pollyjs/core';
import XHRAdapter from '@pollyjs/adapter-xhr';
import FetchAdapter from '@pollyjs/adapter-fetch';
import RESTPersister from '@pollyjs/persister-rest';

/*
  Register the adapters and persisters we want to use. This way all future
  polly instances can access them by name.
*/
Polly.register(XHRAdapter);
Polly.register(FetchAdapter);
Polly.register(RESTPersister);

describe('Netflix Homepage', function () {
  it('should be able to sign in', async function () {
    /*
      Create a new polly instance.

      Connect Polly to both fetch and XHR browser APIs. By default, it will
      record any requests that it hasn't yet seen while replaying ones it
      has already recorded.
    */
    const polly = new Polly('Sign In', {
      adapters: ['xhr', 'fetch'],
      persister: 'rest'
    });
    const { server } = polly;

    /* Intercept all Google Analytic requests and respond with a 200 */
    server
      .get('/google-analytics/*path')
      .intercept((req, res) => res.sendStatus(200));

    /* Pass-through all GET requests to /coverage */
    server.get('/coverage').passthrough();

    /* start: pseudo test code */
    await visit('/login');
    await fillIn('email', '[email protected]');
    await fillIn('password', '@pollyjs');
    await submit();
    /* end: pseudo test code */

    expect(location.pathname).to.equal('/browse');

    /*
      Calling `stop` will persist requests as well as disconnect from any
      connected browser APIs (e.g. fetch or XHR).
    */
    await polly.stop();
  });
});

The above test case would generate the following HAR file which Polly will use to replay the sign-in response when the test is rerun:

{
  "log": {
    "_recordingName": "Sign In",
    "browser": {
      "name": "Chrome",
      "version": "67.0"
    },
    "creator": {
      "name": "Polly.JS",
      "version": "0.5.0",
      "comment": "persister:rest"
    },
    "entries": [
      {
        "_id": "06f06e6d125cbb80896c41786f9a696a",
        "_order": 0,
        "cache": {},
        "request": {
          "bodySize": 51,
          "cookies": [],
          "headers": [
            {
              "name": "content-type",
              "value": "application/json; charset=utf-8"
            }
          ],
          "headersSize": 97,
          "httpVersion": "HTTP/1.1",
          "method": "POST",
          "postData": {
            "mimeType": "application/json; charset=utf-8",
            "text": "{\"email\":\"[email protected]\",\"password\":\"@pollyjs\"}"
          },
          "queryString": [],
          "url": "https://netflix.com/api/v1/login"
        },
        "response": {
          "bodySize": 0,
          "content": {
            "mimeType": "text/plain; charset=utf-8",
            "size": 0
          },
          "cookies": [],
          "headers": [],
          "headersSize": 0,
          "httpVersion": "HTTP/1.1",
          "redirectURL": "",
          "status": 200,
          "statusText": "OK"
        },
        "startedDateTime": "2018-06-29T17:31:55.348Z",
        "time": 11,
        "timings": {
          "blocked": -1,
          "connect": -1,
          "dns": -1,
          "receive": 0,
          "send": 0,
          "ssl": -1,
          "wait": 11
        }
      }
    ],
    "pages": [],
    "version": "1.2"
  }
}

Prior Art

The "Client Server" API of Polly is heavily influenced by the very popular mock server library pretender. Pretender supports XHR and Fetch stubbing and is a great lightweight alternative to Polly if your project does not require persisting capabilities or Node adapters.

Thank you to all contributors especially the maintainers: trek, stefanpenner, and xg-wang.

Contributors

License

Copyright (c) 2018 Netflix, Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

pollyjs's People

Contributors

agraves avatar brandon-leapyear avatar cibernox avatar danielruf avatar dciccale avatar denrizsusam avatar dependabot[bot] avatar dustinsoftware avatar ericclemmons avatar fastfrwrd avatar feinoujc avatar gribnoysup avatar jamesgeorge007 avatar jasonmit avatar jomaxx avatar josex2r avatar justsml avatar karlhorky avatar kennethlarsen avatar offirgolan avatar poteto avatar rmachielse avatar ropdebee avatar rwd avatar silverchen avatar snehajalukar avatar swashcap avatar tombh avatar woodenconsulting avatar zkwentz 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  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

pollyjs's Issues

When does PollyJS record automatically?

Hey, I'm failing to understand when / how PollyJS records and when not.

For eg. by default the recordIfMissing flag is set to true, so when I first run a test PollyJS records it right?
But it seems that when I rerun the test then some of the same requests that were in the recording before get appended / inserted into the recording again, and it keeps on growing (I've diffed some of them and the only difference was timestamp and created_at).

This is probably my misunderstanding of how it works, do you know why this could be happening?

Cannot set/use Response URL using client-side server

I have a piece of code that makes two requests in parallel. When I have both responses I use the URL of the response objects to decide how to handle the response data.

I've set up Polly using a client-side server but the response URLs are coming back as empty strings. I have tried a couple of different ways of setting the URL in my generated response objects but nothing seems to work. I am currently digging into the source code to see if I can identify a method of achieving the results I need but I so far haven't found anything.

Am I missing something? I can try and provide a reduced test case if needed.
Is this something that you would consider adding or accepting a PR for?

Thanks!

feature: UI tool or browser extension

Hi,
I like idea what your library is doing. But it could be much nicer when there be some tool like leonardojs on top of polly.js. Especially when you want to code without backend. Mostly I would prefer some kind of script with browser extension companion.

Conditional request interception and shared request recordings

In our app we have many tests that make similar, or in some cases identical requests. Examples of such request are user and config data used by the app.

We can manually pull down this data and save it as a fixture that we load and use during a request interception but it would be great if there was a way to designate some requests as shared between recordings (using some kind tag or key).

Another option would be to have the capability to intercept a request and have some API for breaking out of the interception (let Polly handle it as usual).

I guess these are two rather different ideas but I think they might both be useful.

Add ability to configure window in fetch adapter.

In E2E frameworks like cypress fetch is attached to an injected window object like this:

cy.visit('my/pathname/', {
  onBeforeLoad: win => { ... }
})

Currently the fetch adapter expects fetch to be attached to self but in this case it's not so it would be nice if I could supply the window object to the fetch adapter or Polly constructor. E.g.

cy.visit('my/pathname/', {
  onBeforeLoad: win => {
    const polly = new Polly('my-polly-recording', {
      adapters: [['fetch', FetchAdapter.create({ window: win })]]
    });
  }
})

feature: IE11 support

Hey, I've been trying out pollyjs in an Ember.js app, and noticed that the app won't work at all because the imported pollyjs files include statements like arrow functions which don't work with IE.

The issue seems to be that the Polly.js addon uses app.import to include the libraries, but afaik app.import doesn't run the code through webpack, so it doesn't transform it into viable ES5 code. It just includes the code verbatim.

edit: btw sidenote, shouldn't pollyJS be included only when running in the test environment by default?

Does not install since 1.0.0

Installing with:
npm install @pollyjs/core

Produces this error:

npm ERR! code ETARGET
npm ERR! notarget No matching version found for @pollyjs/utils@^1.0.0
npm ERR! notarget In most cases you or one of your dependencies are requesting
npm ERR! notarget a package version that doesn't exist.
npm ERR! notarget
npm ERR! notarget It was specified as a dependency of '@pollyjs/core'
npm ERR! notarget

It appears utils 1.0.0 isn't published but core is?

cannot get records

i use @pollyjs/node-server to init a server, the followed is my code:

const { Server } = require('@pollyjs/node-server');
const path = require('path');

const server = new Server({
  quiet: true,
  port: 4000,
  apiNamespace: '/pollyjs',
  recordingsDir: path.join(__dirname, '/recordings')
});

// Add custom business logic to the express server
server
  .app
  .get('/custom', (req, res) => { 
        console.log(`Custom request >> > `);
        res.status(200).json("Successfully");
   });

// Start listening and attach extra logic to the http server
server
  .listen()
  .on('error', () => { /* Add http server error logic */ });

When I request http://localhost:4000/custom , system cannot records any request history.

I use node v10.7.0

[Question] Creating nearly identical records with different date headers.

Hello everybody! polyJs is awesome, but I have a little question (maybe I misundersand something or how it works, or not :))
Suppose, we have following code:

new Polly(recordingName, {
    adapters: ['puppeteer'],
    persister: ['fs'],
    adapterOptions: {
        puppeteer: { page }
    },
    persisterOptions: {
        fs: {
            recordingsDir: 'tests/__recordings__',
        },
    },
    matchRequestsBy: {
        headers: {
            exclude: [
                'x-csrf-token',
                'user-agent',
                'date',
            ],
        },
        url: {
            port: false,
            hostname: false,
            protocol: false,
        },
        order: false,
    },
});

And, if I run the same test in diffrent dates (for e.g. yesterday and today), I recieve in my recording.har
duplicated entries that are different only in few fields (note: it's response headers):
diff

I guess that due to date header difference my recordings are considered different.
So, the question:
If I explictly set exclude rule for 'date' header during Polly initialization - why I doesn't work?
Or it is intended for another thing?

Thank you.

How to wait for all the responses to finish?

Is there anything like fetchMock.fush() ?
http://www.wheresrhys.co.uk/fetch-mock/api#flush
This is how they do it:

FetchMock.flush = function() {
	return Promise.all(this._holdingPromises);
};
FetchMock.fetchHandler = function(url, opts) {
	const response = this.executeRouter(url, opts);

	[...]

	// this is used to power the .flush() method
	let done;
	this._holdingPromises.push(new this.config.Promise(res => (done = res)));

	// wrapped in this promise to make sure we respect custom Promise
	// constructors defined by the user
	return new this.config.Promise((res, rej) => {
		this.generateResponse(response, url, opts)
			.then(res, rej)
			.then(done, done);
	});
};

Polly not passing requests through to react app server?

Hi,
I'm using Polly in a react app where I'm writing Selenium tests. Basically, react is running on localhost:3000 and selenium spins up a browser, which I can point to my react app to click on things, and everyone is happy. But now, I'm trying to stub out all my API requests (XHR) using Polly.
I run Polly with polly l, so it listens on port 3000. Now, both my react app and Polly is running on localhost:3000.

I have set up polly like this:

Polly.register(XHRAdapter)
Polly.register(LocalStoragePersister);

const polly = new Polly('Sign In', {
  adapters: ['xhr'],
  persister: 'local-storage'
});
const { server } = polly;

polly.configure({
  persisterOptions: {
    'local-storage': {
      key: '__pollyjs__'
    }
  }
});

polly.connectTo('xhr')

server.get('http://localhost:3000/slam-ui').passthrough()

The first thing I do in my test is to instruct selenium to go to http://localhost:3001/slam-ui and be passed through by Polly to actually reach my react app, but instead, this is what polly outputs:

screen shot 2018-09-11 at 09 32 30

And the selenium browser only shows "Can't get "/slam-ui", so a just a 404.
I must be missing something fundamental here?

No HAR file generated by fs persister

When running a test using the puppeteer adapter and fs persister, I don't see any HAR file being generated.

This is the code for the test:

const puppeteer = require('puppeteer');
const Polly = require('@pollyjs/core').Polly;
const PuppeteerAdapter = require('@pollyjs/adapter-puppeteer');
const FSPersister = require('@pollyjs/persister-fs');

describe('Testing Pollyjs', function() {

  beforeEach(async function () {
    browser = await puppeteer.launch({
      headless: true, 
      args: ['--no-sandbox']
    });
  });

  afterEach(async function() {
    await browser.close();
  });
    
  it('Does foo', async function() {
    let page = await browser.newPage();
    await page.setRequestInterception(true);
  
    Polly.register(PuppeteerAdapter);
    Polly.register(FSPersister);
      
    const polly = new Polly('first recording', {
      adapters: ['puppeteer'],
      adapterOptions: {
        puppeteer: { page }
      },
      persister: 'fs',
      persisterOptions: {
        fs: { recordingsDir: '../recordings' }
      },
      logging: true
    })

    polly.connectTo('puppeteer');
    await page.goto('http://www.google.com/')
    polly.disconnectFrom('puppeteer');
    await polly.stop();
  });
});

This is a tree command (ignoring node_modules) of the directory after the test runs, showing no HAR file present in the recordings directory:

.
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ package-lock.json
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ recordings
โ””โ”€โ”€ test
    โ””โ”€โ”€ polly-test.js

I'm not sure what the issue actually is; my apologies for opening an issue for this but I wasn't able to infer from the documentation what I needed to do. I should probably also use setupMocha in the test structure, but I don't think the fact that this missing is the issue. Any pointers would be appreciated!

Cannot read property 'timestamp' of undefined

I add this code for my project
but hit error...

https://netflix.github.io/pollyjs/#/server/overview

import {Polly} from "@pollyjs/core"; 

const polly = new Polly('<Recording Name>');
const { server } = polly;

// Events & Middleware
server
  .any()
  .on('request', (req, res) => {
    req.headers['X-Auth-Token'] = 'abc123';
  });

// Intercept requests
server.get('/session').intercept((req, res) => {
  res.status(200).json({ user: { email: '[email protected]' } });
});

// Passthrough requests
server.get('/coverage').passthrough();

Uncaught (in promise) TypeError: Cannot read property 'timestamp' of undefined
at n.value (pollyjs-core.js?2fca:1)
at eval (pollyjs-core.js?2fca:1)
at w (pollyjs-core.js?2fca:1)
at Generator.eval [as _invoke] (pollyjs-core.js?2fca:1)
at Generator.l.(:8088/anonymous function) [as next] (webpack-internal:///./node_modules/@pollyjs/core/dist/umd/pollyjs-core.js:1:12578)
at e (pollyjs-core.js?2fca:1)
at eval (pollyjs-core.js?2fca:1)
value @ pollyjs-core.js?2fca:1
(anonymous) @ pollyjs-core.js?2fca:1
w @ pollyjs-core.js?2fca:1
(anonymous) @ pollyjs-core.js?2fca:1
l.(anonymous function) @ pollyjs-core.js?2fca:1
e @ pollyjs-core.js?2fca:1
(anonymous) @ pollyjs-core.js?2fca:1

Puppeteer adapter + Rest persister does not work.

The problem is that global.XMLHttpRequest which rest persister uses is not defined. I have tried adding xhr adapter, jus to see if it will make a difference, but I got [Polly] [adapter:xhr] XHR global not found because I use puppeteer

options

{
      adapters: ['puppeteer'],
      persister: 'rest',
      adapterOptions: {
        puppeteer: { page },
      },
      persisterOptions: {
        rest: {
          host: 'http://localhost:8080',
        },
      },
}

error

TypeError: NativeXMLHttpRequest is not a constructor

      at _Promise (node_modules/@pollyjs/persister-rest/dist/cjs/pollyjs-persister-rest.js:1289:17)
      at new F (node_modules/@pollyjs/persister-rest/dist/cjs/pollyjs-persister-rest.js:210:28)
      at ajax (node_modules/@pollyjs/persister-rest/dist/cjs/pollyjs-persister-rest.js:1288:10)
      at RestPersister.ajax (node_modules/@pollyjs/persister-rest/dist/cjs/pollyjs-persister-rest.js:1345:12)
      at node_modules/@pollyjs/persister-rest/dist/cjs/pollyjs-persister-rest.js:1352:36
      at step (node_modules/@pollyjs/persister-rest/dist/cjs/pollyjs-persister-rest.js:1227:30)
      at node_modules/@pollyjs/persister-rest/dist/cjs/pollyjs-persister-rest.js:1245:14

Jest Support?

Hi looks like a great project, can I use it with Jest?

[Question] Recommended usages

Would you recommend / do you use Polly for end-to-end tests? Meaning tests that are intended to test both UI and API functionality.

If yes, do you have any patterns you follow?

If no, why not?

How can i use polly on a simple test project?

Hi!

I'm found PollyJS on github trending repos, and i'm curious about how it works and how it can help me on my projects. So i've create a simple node app like:

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

i've already run:

npm install @pollyjs/cli -g
npm install @pollyjs/core -D

But i'm a little bit lost on where should i have to code the sample:

import { Polly } from '@pollyjs/core';

describe('Netflix Homepage', function() {
  it('should be able to sign in', async function() {
    /*
      Create a new polly instance.

      By default, Polly will connect to both fetch and XHR browser APIs and
      will record any requests that it hasn't yet seen while replaying ones it
      has already recorded.
    */
    const polly = new Polly('Sign In');

    /* start: pseudo test code */
    await visit('/login');
    await fillIn('email', '[email protected]');
    await fillIn('password', '@pollyjs');
    await submit();
    /* end: pseudo test code */

    expect(location.pathname).to.equal('/browse');

    /*
      Calling `stop` will persist requests as well as disconnect from any
      connected browser APIs (e.g. fetch or XHR).
    */
    await polly.stop();
  });
});

Thanks in advance!

Error when adding the 'beforeRecord' event

Hey, I've been testing pollyjs in my Ember app, and it worked fine. Later I've added the beforeRecord event like this:

    server
      .any()
      .on('beforeRecord', (req, recording) => {
        console.log(recording);
      });

and got this error (it goes away when I remove it):

pollyjs-core.js:2 Uncaught (in promise) TypeError: Cannot assign to read only property 'params' of object '#<l>'
    at pollyjs-core.js:2
    at tryCatch (polyfill.js:6900)
    at Generator.invoke [as _invoke] (polyfill.js:7138)
    at Generator.prototype.(:7357/3066/tests/anonymous function) [as next] (http://localhost:7357/assets/vendor.js:12297:21)
    at t (pollyjs-core.js:2)
    at pollyjs-core.js:2
    at new Promise (<anonymous>)
    at new n (pollyjs-core.js:2)
    at pollyjs-core.js:2
    at pollyjs-core.js:2

(btw it'd be nice if source maps would work when in dev mode, so that it would be easier to debug issues like this)

npm run test - throws error

$ npm run test

@ pretest /Users/svittalagupta/plugins/poly/pollyjs
yarn server:build

yarn run v1.7.0
$ yarn build --scope=@pollyjs/node-server --scope=@pollyjs/utils
$ lerna run build --ignore=@pollyjs/ember --parallel --scope=@pollyjs/node-server --scope=@pollyjs/utils
lerna info version 2.11.0
lerna info versioning independent
lerna info scope [ '@pollyjs/node-server', '@pollyjs/utils' ]
lerna info ignore @pollyjs/ember
lerna info run in 2 package(s): npm run build
@pollyjs/node-server: $ npm-run-all clean rollup
@pollyjs/utils: $ npm-run-all clean rollup
@pollyjs/utils: /bin/sh: npm-run-all: command not found
@pollyjs/node-server: /bin/sh: npm-run-all: command not found
@pollyjs/utils: info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
@pollyjs/node-server: info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
@pollyjs/node-server: error Command failed with exit code 127.
@pollyjs/utils: error Command failed with exit code 127.
lerna ERR! execute callback with error
lerna ERR! Error: Command failed: yarn run build
lerna ERR! /bin/sh: npm-run-all: command not found
lerna ERR! error Command failed with exit code 127.
lerna ERR!
lerna ERR! $ npm-run-all clean rollup
lerna ERR! info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
lerna ERR!
lerna ERR! at Promise.all.then.arr (/Users/svittalagupta/plugins/poly/pollyjs/node_modules/execa/index.js:236:11)
lerna ERR! at
lerna WARN complete Waiting for 1 child process to exit. CTRL-C to exit immediately.
{ Error: Command failed: yarn run build
/bin/sh: npm-run-all: command not found
error Command failed with exit code 127.

$ npm-run-all clean rollup
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

at Promise.all.then.arr (/Users/svittalagupta/plugins/poly/pollyjs/node_modules/execa/index.js:236:11)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)

code: 1,
killed: false,
stdout: '$ npm-run-all clean rollup\ninfo Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.\n',
stderr: '/bin/sh: npm-run-all: command not found\nerror Command failed with exit code 127.\n',
failed: true,
signal: null,
cmd: 'yarn run build',
timedOut: false,
exitCode: 1 }
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! @ pretest: yarn server:build
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the @ pretest script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! /Users/svittalagupta/.npm/_logs/2018-07-31T04_29_30_662Z-debug.log

UnhandledPromiseRejectionWarning after upgrade

I'm using the following npm packages

"@pollyjs/adapter-fetch": "^1.0.0",
"@pollyjs/core": "^1.0.0",
 "@pollyjs/persister-fs": "^1.0.0",

If I try to upgrade @pollyjs/core to 1.1.0 or higher I get the following warnings running my tests with Jest:

(node:16928) UnhandledPromiseRejectionWarning: Error: [Polly] [adapter:fetch] Unhandled request: GET http://localhost/api/gas-types/.
(node:16928) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 6)
(node:16928) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:16928) UnhandledPromiseRejectionWarning: Error: [Polly] [adapter:fetch] Unhandled request: GET http://localhost/api/location/.
(node:16928) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .

any ideas how to figure it out why?

TypeError: Invalid value used as weak map key

Hi,

While trying this out, I got the error TypeError: Invalid value used as weak map key

My test code looks roughly like:

const puppeteer = require('puppeteer');
const Polly = require('@pollyjs/core').Polly;
const { PuppeteerAdapter } = require('@pollyjs/adapter-puppeteer');

// skipping setup/teardown in this example
it('does foo', async function() {
  let page = await browser.newPage();

  Polly.register(PuppeteerAdapter);
  await page.setRequestInterception(true);

  const polly = new Polly('first_recording', {
    adapters: ['puppeteer'],
    adapterOptions: {
      puppeteer: { page }
    }
  });

  polly.connectTo('puppeteer');
  await page.goto('http://example.com');
  polly.disconnectFrom('puppeteer');

});

The stack trace:

     TypeError: Invalid value used as weak map key
      at WeakMap.set (native)
      at WeakMap.<anonymous> (node_modules/@pollyjs/core/dist/cjs/pollyjs-core.js:1586:34)
      at Function.register (node_modules/@pollyjs/core/dist/cjs/pollyjs-core.js:4054:28)
      at Context.<anonymous> (test/pollyjs-hello-world.js:129:13)
      at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:188:7)

I'm running node v8.11.3. Help!

How do I use Polly.js for pure request mocking (no recording, no-replaying, etc)

The current thing I'm trying to mock is my current-user endpoint.

I have /api/users/current-user and my mock for it:

    const { server } = this.polly;

    server.get('/api/users/current-user').intercept((req, res) => {
      res.status(200);
      res.json({
        data: {
          attributes: { id: 1, auth0Id: 'my-fake-auth0Id' }
        }
      });
    });

This project is open source, and the above snippet can be viewed here: https://github.com/sillsdev/appbuilder-portal/blob/f76a67e1600c36fff1de8eb2ff2bbbeafc91517b/source/SIL.AppBuilder.Portal.Frontend/tests/helpers/auth.ts#L16:L24

The configuration for polly is configured as follows:

import { Polly } from '@pollyjs/core';

// inspiration from:
// https://github.com/Netflix/pollyjs/blob/master/packages/%40pollyjs/core/src/test-helpers/mocha.js
export function setupRequestInterceptor(config: any = {}) {
  beforeEach(function() {
    const name = generateRecordingName(this);
    const pollyConfig = {
      mode: 'passthrough',
      logging: true,
      recordIfMissing: false,
      matchRequestBy: {
        order: false,
        url: {
          port: false,
          hostname: false,
          protocol: false,
        }
      },
      ...config
    };

    this.polly = new Polly(name, pollyConfig);

    const { server } = this.polly;

    // by default? stub out auth0 so that auth0/lock.js doesn't
    // try to contact auth0 during testing.
    server.options('/api/*anypath').intercept((req, res) => {
      console.log('req', req);
      req.headers.Allow = 'OPTIONS, GET, HEAD, POST, PUT, PATCH, DELETE, TRACE';
    });

    server.get('https://cdn.auth0.com/*path').intercept((req, res) => {
      res.status(200);
      res.json({});
    });
  });

  afterEach(async function() {
    await this.polly.stop();
  });
}


// helpers stolen from:
// https://github.com/Netflix/pollyjs/blob/master/packages/%40pollyjs/core/src/test-helpers/lib.js
export function generateRecordingName(context) {
  // ... omitted for brevity
}

so, when my test makes a call to /api/users/current-user (as it would on a route that requires authentication), I get NOT FOUND errors:

image

image

I'm using karma + mocha for my tests, so http://localhost:9876/debug.html is the address where I run my tests in debug mode (which is why the full URL for the current-user route has localhost:9876).

So, am I doing anything obviously wrong?

Examples of Polly.js with Selenum/WebDriver would be fantastic

Not only a Node.js+WebDriver.js example, but Java, Python, Ruby and C# ones too, with their respective Selenium/WebDriver bindings.

To make it easy for authors of these examples, tech from http://todobackend.com/ is a decent starting point, like I did for https://paulhammant.com/2017/02/05/a-16-second-java-webapp-build-including-webdriver-tests/. In that case I didn't use a mocking technology like Mountebank, I wove in my own mocks interaction into the in-JVM model, and interoperated with them directly during the UI-clicking test execution.

Set response status to 200 by default

In most cases right now I'm using something like

res.status(200);
res.json({ ... });

but I think that could be simplified by making status: 200 the default, which is currently set to null according to the logging.

Is there any reason why 200 should not be the default?

Unexpected token import

Hi, please can you help me with dummy explanation how to run pollyjs tests in mocha? I am trying to execute this short script (with all modules installed globally via npm 5.6.0 / node v8.11.1):

`var Polly = require('@pollyjs/core');

describe('VALO login', function () {

it('vp admin sign in true', async function() {
    const polly = new Polly('App log in', {
        persisterOptions: {
            host: 'http://v2appenv01',
        }
    });

    await visit('/#/');
    await fillIn('username','test.admin');
    await fillIn('password','password');
    await submit();

    expect(location.pathname).to.equal('/#/list');

    await polly.stop();

});

});`

and the results is:

`mocha polly_login_test.js
C:\Users\spsch\AppData\Roaming\npm\node_modules@pollyjs\core\src\polly.js:1
(function (exports, require, module, __filename, __dirname) { import mergeOptions from 'merge-options';
^^^^^^

SyntaxError: Unexpected token import
at createScript (vm.js:80:10)
at Object.runInThisContext (vm.js:139:10)
at Module._compile (module.js:616:28)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
at Object. (C:\Users\spsch\code\valo\src\test\javascript\e2e\prague_test\polly_login_test.js:4:13)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
at C:\Users\spsch\AppData\Roaming\npm\node_modules\mocha\lib\mocha.js:250:27
at Array.forEach ()
at Mocha.loadFiles (C:\Users\spsch\AppData\Roaming\npm\node_modules\mocha\lib\mocha.js:247:14)
at Mocha.run (C:\Users\spsch\AppData\Roaming\npm\node_modules\mocha\lib\mocha.js:576:10)
at Object. (C:\Users\spsch\AppData\Roaming\npm\node_modules\mocha\bin_mocha:637:18)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Function.Module.runMain (module.js:693:10)
at startup (bootstrap_node.js:188:16)
at bootstrap_node.js:609:3`

Thank you in advance.

Conflic in ember-cli with the `proxy` option.

If you start your ember-cli with the --proxy option (or you have it set in your .ember-cli) folder seems that polly's middleware is not having a chance of intercepting the requests, causing the requests to be forwarded to the real server.

Not enough information when recording isn't found

Pollyjs only tells the URL and method when a recording isn't found for a request. It's especially difficult to tell which request wasn't matched when using GraphQL, because all requests have the same method and URL. An ideal enhancement would be if it told you why it doesn't match, but just an option for more verbose logging of the missing recording would be very helpful!

Custom Adapter configuration documentation suggestion

Hi pollyjs team,

Thanks for sharing.

I had to dive into pollys internals to understand how best to register a custom adapter as its not immediately clear from the documentation.

Whilst configuring the default adapters is mentioned there is no example to illustrate registering your own.

For reference something like below could be really useful under the configuration.Adapters section.

{
  adapters: [
    ['<myCustomAdapterName>', myCustomAdapter],
  ],
}

Cheers,

Jon

Origins Question, What does Polly.JS offer over VCR/etc?

I was curious if there was anywhere that the origin of Polly was noted. I know that there are record/replay libraries in Ruby (vcr, betamax) and Python (VCR.py, cassette). Was the desire to have a pure Node.js implementation? Were the aspects that were not present in the existing efforts that triggered the need for Polly.JS?

I ask with a sincere desire to understand. I am not involved, nor associated, with any such project. As a community member, it helps me discern and select among a range of sources. I don't know if it makes sense to tag the creators (Jason Mitchell & Offir Golan) or not, so I'll leave that as a mention.

Thank you for making this available to the wider open source community.

Host is stripped from protocol-relative urls

How to reproduce:

  1. Have app on http://my-app.dev
  2. Make request to protocol-relative url //api.dev/posts/1

Expected behavior
Polly proxies this request to api.dev and writes response.

Actual behavior
Polly strips host from //api.dev/posts/1 making it into /posts/1 and then trying to send request to http://my-app.dev/posts/1 instead of original url.

I found two places in code where url is modified. Here is one which caused desribed behavior:

/*
If the url is relative, setup the parsed url to reflect just that
by removing the host. By default URL sets the host via window.location if
it does not exist.
*/
if (!isAbsoluteUrl(value)) {
removeHostFromUrl(url);
}

Seems like is-absolute-url check here can be swapped with custom implementation supporting protocol-relative urls

express integration?

I cannot figure out how to use express integration for API calls that my server proxies. Where/how/what should I be doing to properly save http responses from these APIs so that once saved they are then returned from Pollyjs for all the following requests? My read through the quickstart hasn't led to the desired result. Here is an example of what I'm doing--and don't know where/how to make the above happen. Thanks in advance for any insight and help.. I should add I assume the middleware handles all these requests and writing to files--if that's incorrect please let me know.

const PORT = process.env.PORT || 8444;
const express = require('express');
const request = require('request');

const Polly = require("@pollyjs/core");
const PollyServer = require("@pollyjs/node-server");

const app = express();
PollyServer.registerExpressAPI(app);

app
.use(express.json())
.use(function _httpHandler(req, res, next){
	console.log(`${ req.method } ${ req.url }`);
	req.__api = {}; // TODO
	try{
		// represents proxying to others...
		request({
			url: 'http://localhost' + req.url,
			headers: req.headers,
			method: req.method
		})
		.on('error', (err) => {
			next(err);
		})
		.pipe(res)
		;
	}catch(requestError){
		console.error(requestError);
	};
})
.use(function _httpErrorHandler(err, req, res, next) {
	let msg = (err.message || '').replace(/\n|\r/g, ' ').substr(0, 1000);
	let body = '';

	switch(err.code){
	case 'ENOENT':
		res.status(404);
		msg = `can't find it...`;
	break;
	case 'ECONNREFUSED':
		res.status(503);
		msg = `service unavailable ${req.url}`;
		console.warn(msg);
	break;
	default:
		res.status(500);
		console.error(err);
		// yes, stop and look
		debugger;
	};

	try{
		if(req.__api.json) body = JSON.stringify({error: msg, code: err.code, statusCode: err.statusCode});
		else body = `${msg}

stack:
${err.stack}`;

	}catch(trappedJSONError){
		body = msg;
	};
	res.end(body);
})
.listen( PORT )
;
console.log(`open http://localhost:${PORT}`);

Custom Persister Support

Hi pollyjs team,

I'd like to suggest adding support for specifying a custom persister in a similar fashion to adapters.

{
    persister: ['<myCustomPersisterName>', myCustomPersister],
}

I've managed to get this working and was wondering if you would be open to accepting a PR for this.

It would require a minor change to @pollyjs/core to support registering custom persisters with the container and ideally @pollyjs/core/src/persisters/persister would be promoted to its own package so that it is more accessible i.e @pollyjs/persister similar to adapters.

const persisterConfig = this.config.persister;
let persisterName = persisterConfig;

if(isArray(persisterConfig)) {
    const [, PersisterType] = persisterConfig;
    persisterName = persisterConfig[0];
    this._container.set(`persister:${persisterName}`, PersisterType);
}

this.persister = new (this._container.get(
  `persister:${persisterName}`
))(this);

The context for this suggestion is that with these minor changes its possible for pollyjs to support recording within Node directly meaning I can use pollyjs for both my client & server tests.

I've this working end-to-end and plan on polishing it further.

Cheers,

Jon

Can I have two different intercepts based on query params?

I've tried setting the path passed to get to a path including a query string. but it seems to not registery correctly.

I see this error in the chrome console (this is the request my app is making):

GET http://localhost:9876/api/projects?filter%5Bdate-archived%5D=isnull%3A&include=organization%2Cgroup%2Cowner&page%5Boffset%5D=1&page%5Blimit%5D=20 404 (Not Found)

I've tried:

'/projects?filter[date-archived]=isnull:&include=organization,group,owner&page[offset]=1&page[limit]=20'

and

'/projects?filter%5Bdate-archived%5D=isnull%3A&include=organization%2Cgroup%2Cowner&page%5Boffset%5D=1&page%5Blimit%5D=20'

and neither work.

what does work is not providing any query params at all:

'/projects`

I have this in the polly config:

    matchRequestsBy: {
      order: true,
      headers: true,
      url: {
        pathname: true,
        query: true,
        hash: false
      }
    }

feature: presets for node and browser

@pollyjs/preset-node
@pollyjs/preset-browser

To abstract away setting up the persisters and adapters that are commonly available in each runtime. Will simplify the documentation on getting started.

Turning on Polly makes puppeteer do hundreds of requests

I am using jest + puppeteer to run tests. I am trying to use polly to record and serve requests to our API when running integration tests.

What happens when i turn on Polly to record our requests is that it starts running the same request for hundreds of times.

The packages I am using: PuppeteerAdapter, FSPersister.
When I turn off Polly the request completes successfully.

I recorded a video of the chromium's console:
https://gfycat.com/EssentialShadowyAnura

Here are the versions I am using:

    "@pollyjs/adapter-puppeteer": "^1.1.0",
    "@pollyjs/core": "^1.1.0",
    "@pollyjs/persister-fs": "^1.0.1",

and the configs:

Server

{
      recordingsDir: path.join(__dirname, 'recordings'),
      quiet: false,
      port: 3001,
      host: 'localhost'
}

Polly

{
      adapters: ['puppeteer'],
      adapterOptions: {
        puppeteer: { page }
      },
      persister: 'fs',
      persisterOptions: {
        host: 'http://localhost:3001'
      },
      logging: true
}

Is there something I am missing in the config? Or in general?

Trouble proxying http requests to localhost server using Ember

I'm trying to get HTTP requests to proxy to my local api server, which is running on port 3000 on my machine.

I've configured polly as such:

    pollyjs: {
      enabled: EmberApp.env() !== 'production',
      server: {
        apiNamespace: 'polly',
        recordingsDir: 'recordings'
      }
    }

If I just start the app using ember s then the api calls do not get proxied over to my local server. This isn't suprising, since I haven't told the app anywhere to do so. If I start the app using ember s -proxy=http://localhost:3000 then the ember app tries to forward the call to polly over to my local server, which obviously doesn't exist and returns a 404:

http://localhost:4200/polly/Acceptance-Projects-Test_1427335148%2FList-of-Projects_1960582640/c7891a5bc919b6b46c122f196338f0b2?order=0

Looking at the documentation, I'm unclear how to get this working. Is there some sort of configuration I need to do in the express server created by polly on the ember app? Or did I just configure polly wrong in .ember-cli-build?

Also I have a test app up with the code I'm using https://github.com/andrewcallahan/test-app

Thanks in advance! Really hoping to get this working!

Is it possible to record from node?

I would like to record some API tests run from node.
Everytime I run my node.js api test it should update the persisted content.

Then I would like to run my frontend apps tests, but never reaching my real API, every request should return from the cached version.

How can I achieve this? Do I have write an adapter, if Iโ€™m using node-fetch which have the exact same api as the browser version?

jsdom support?

I got next error when tried to use it in browser-like environment:

console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
    Error: Error: Invalid URI "about:/polly/SimilarItems_366191554"

Import polly is failing

I'm trying to use polly on Ember 3.1.4, but can't seem to get the import to work.

I installed it via ember install @pollyjs/ember, set the configuration, and then tried to import the module in an empty acceptance test file. However, the importing import { setupQunit as setupPolly } from '@pollyjs/core'; is failing.

Here is the error message:

Source: 	
Error: Could not find module `@pollyjs/core` imported from `test-app/tests/acceptance/projects-test`

Cannot register any adapters.

This error happens before I even create a polly instance. When I'm just registering adapters...

image

image

image
image

Unfortunately, my stack trace and sourcemaps are worthless because webpack, karma, and typescript are apparently not friends with each other...

So, with no registered adapters, I can create a Polly instance.

  import { Polly } from '@pollyjs/core';
// import XHRAdapter from '@pollyjs/adapter-xhr';
import FetchAdapter from '@pollyjs/adapter-fetch';

// Polly.register(XHRAdapter);
// Polly.register(FetchAdapter);

// creating poly instance omitted, because it doesn't matter here :)

When I try to register an adapter, I get an error:

  import { Polly } from '@pollyjs/core';
// import XHRAdapter from '@pollyjs/adapter-xhr';
import FetchAdapter from '@pollyjs/adapter-fetch';

// Polly.register(XHRAdapter);
Polly.register(FetchAdapter);

// creating poly instance omitted, because it doesn't matter here :)

This error happens when I don't even specify what adapters to use in the configuration object. (adapters: []);

So, I think this may be a problem with register?

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.