Coder Social home page Coder Social logo

assaf / node-replay Goto Github PK

View Code? Open in Web Editor NEW
522.0 14.0 107.0 732 KB

When API testing slows you down: record and replay HTTP responses like a boss

Home Page: http://documentup.com/assaf/node-replay

License: MIT License

Makefile 0.87% JavaScript 99.13%

node-replay's Introduction

Node Replay

When API testing slows you down: record and replay HTTP responses like a boss

Things that will ruin your day when tests make HTTP requests to other services:

  • That other service has the uptime of Twitter's API
  • Network late ............ ncy
  • Being-rate limited and having to wait an hour for the next test run
  • Same request returns different result each time
  • Everyone else on the network is deep in BitTorrent territory

Things node-replay can do to make these problems go away:

  • Record API response once, replay as often as necessary
  • Stub HTTP requests (TBD)
  • Replay different responses to same request (great for testing error handling)
  • Not suck

How to use node-replay

Like this:

npm install replay

Now write some simple test case:

const assert  = require('assert');
const HTTP    = require('http');
const Replay  = require('replay');

HTTP.get({ hostname: 'www.iheartquotes.com', path: '/api/v1/random' }, function(response) {
  var body = '';
  response.on('data', function(chunk) {
    response.body = response.body + chunk;
  });
  response.on('end', function() {

    // Now check the request we made to the I <3 Quotes API
    assert.equal(response.statusCode, 200);
    assert.equal(response.body, 'Oxymoron 2. Exact estimate\n\n[codehappy] http://iheartquotes.com/fortune/show/38021\n');
    console.log('Woot!');

  });
});

This, of course, will fail the first time you run it. You'll see:

Error: Connection to http://www.iheartquotes.com:80/api/v1/random refused: not recording and no network access
    at Array.0 (/Users/assaf/projects/node-replay/lib/replay/proxy.coffee:87:21)
    at EventEmitter._tickCallback (node.js:192:40)

Unless you tell it otherwise, node-replay runs in replay mode. In this mode it will replay any previously captured HTTP response, but it will not allow any outgoing network connection.

That's the default mode for running tests. "Why?" you ask. Good question. Running in replay mode forces any test you run to use recorded reponses, and so it will run (and fail or pass) the same way for anyone else, any other day of the week, on whatever hardware they use. Even if they're on the AT&T network.

Running in replay mode helps you write repeatable tests. Repeatable tests are a Good Thing.

So the first thing you want to do to get that test to pass, is to run node-replay in record mode. In this mode it will replay any recorded response, but if no response was recorded, it will make a request to the server and capture the response.

Let's do that:

REPLAY=record node test.js

That wasn't too hard, but the test is still failing. "How?" You must be wondering and scratching your head in total disbelief. It's actually quite simple.

Every request you make to 'I 3> Quotes' returns a different quote, and that test is looking for a very specific quote. So the test will fail, and each time fail with a different error.

So one way we can fix this test is to change the assertion. Look at the error message, get the actual quote and make the assertion look for that value.

Now run the test:

$ node test.js
=> Woot!

Did the test pass? Of course it did. Run it again. Still passing? Why, yes.

So let's have a look at that captured response. All the respones recorded for 'I <3 Quotes>' will be listed here:

ls fixtures/www.iheartquotes.com/

There should be only one file there, since we only recorded one response. The file name is a timestamp, but feel free to rename it to something more descriptive.

The name of a response file doesn't matter, it can be whatever you want. The name of the directory does, though, it matches the service hostname (and port when not 80).

So that was one way to fix the failing test. Another one is to change the recorded response to match the assertion. Being able to edit (and create new) responses is quite important. Sometimes it's the easiest way to create mock responses for testing, e.g. if you're trying to test failure conditions that are hard to come by.

So let's edit the response file and change the body part, so the entire response reads like this:

/api/v1/random

HTTP/1.1 200 OK
server: nginx/0.7.67
date: Fri, 02 Dec 2011 02:58:03 GMT
content-type: text/plain
connection: keep-alive
etag: "a7131ebc1e81e43ea9ecf36fa2fdf610"
x-ua-compatible: IE=Edge,chrome=1
x-runtime: 0.158080
cache-control: max-age=0, private, must-revalidate
content-length: 234
x-varnish: 2274830138
age: 0
via: 1.1 varnish

Oxymoron 2. Exact estimate

[codehappy] http://iheartquotes.com/fortune/show/38021

All responses are stored as text files using the simplest format ever, so you can edit them in Vim, or any of the many non-Vim text editors in existence:

  • First comes the request path (including query string)
  • Followed by any headers sent as part of the request (like Accept and Authorization)
  • Then an empty line
  • Next the response status code and (optional) HTTP version number
  • Followed by any headers sent as part of the response
  • Then another empty line
  • And the rest taken by the response body

If you need to use regular expressions to match the request URL, add REGEXP between the method and path, for example:

GET REGEXP /\/Aregexp\d/i

HTTP/1.1 200 OK
Content-Type: text/html

Settings

We've got them. Just enough to make you happy and not enough to take all day to explain.

The first and most obvious is the mode you run node-replay in:

bloody -- All requests go out, none get replayed. Use this if you want to remember what life was before you started using node-replay. Also, to test your code against changes to 3rd party API, because these do happen. Too often.

cheat -- Replays recorded responses, and allow HTTP outbound requests. This is mighty convenient when you're writing new tests or changing code to make new, un-recorded HTTP requests, but you haven't quite settled on which requests to make, so you don't want any responses recorded quite yet.

record -- Replays recorded responses, or captures responses for future replay. Use this whenever you're writing new tests or code that makes new HTTP requests.

replay -- Replays recorded responses, does not allow outbound requests. This is the default mode. That's another way of saying, "you'll be running in this mode most of the time".

You can set the mode by setting the environment variable REPLAY to one of these values:

REPLAY=record node test.js

Of from your code by setting replay.mode:

const Replay = require('replay');
Replay.mode = 'record';

Of course, node-replay needs to store all those captured responses somewhere, and by default it will put them in the directory fixtures. Bet you have an idea for a better directory name. Easy to change.

Like this:

Replay.fixtures = __dirname + '/fixtures/replay';

You can tell node-replay what hosts to treat as "localhost". Requests to these hosts will be routed to 127.0.0.1, without capturing or replay. This is particularly useful if you're making request to a test server and want to use the same URL as production.

For example:

Replay.localhost('www.example.com');

If you don't want requests going to specific server, you can add them to the drop list. For example, Google Analytics, where you don't care that the request go through, and you don't want to record it.

Replay.drop('www.google-analytics.com', 'rollbar.com');

Likewise, you can tell node-replay to pass through requests to specific hosts:

Replay.passThrough('s3.amazonaws.com');

If you're running into trouble, try turning debugging mode on. It helps. Sometimes.

$ DEBUG=replay node test.js
=> Requesting http://www.iheartquotes.com:80/api/v1/random
=> Woot!

By default, node-replay will record the following headers with each request, and use only these headers when matching pre-recorded requests:

  • Headers starting with Accept (eg Accept-Encoding)
  • Authorization
  • Body (used to match the body of a POST request)
  • Content-Type
  • Host
  • Headers starting with If- (eg If-Modified-Since)
  • Headers starting with X- (eg X-Requested-With)

You can modify the list of matched headers, adding or removing headers, by changing the value of Replay.headers. The value is an array of regular expressions.

For example, to capture content-length (useful with file uploads):

Replay.headers.push(/^content-length/);

Since headers are case insensitive, we always match on the lower case name.

If you want more control over the responses that you record (for example weeding out error responses for really flaky backends or when you are polling waiting for something to happen), you can use recordReponseControl to excercise fine grain control over the recording process. For example, to only save the responses from myhostame.com port 8080 if the response was successful:

Replay.recordResponseControl = {
  "myhostname.com:8080" : function(request, response) {
    return response.statusCode < 400;
  }
};

Geeking

To make all that magic possible, node-replay replaces require('http').request with its own method. That method returns a ProxyRequest object that captures the request URL, headers and body.

When it's time to fire the request, it gets sent through a chain of proxies. The first proxy to have a response, returns it (via callback, this is Node.js after all). That terminates the chain. A proxy that doesn't have a response still has to call the callback, but with no arguments. The request will then pass to the next proxy down the chain.

The proxy chain looks something like this:

  • Logger dumps the request URL when running with DEBUG=replay
  • The pass-through proxy will pass the request directly to the server in bloody mode, or when talking to localhost
  • The recorder proxy will either replay a captured request (if it has one), talk to the server and capture the response (in record mode), or pass to the next proxy
  • The pass-through proxy (2nd one) will pass the request to the server in cheat mode, return nothing in all other modes

Loading pre-recorded responses to memory, from where they can be replayed, and storing new ones on disk, is handled by ... cue big band ... the Catalog.

Final words

node-replay is released under the MIT license. Pull requests are welcome.

node-replay's People

Contributors

albertogasparin avatar assaf avatar cheesefactory avatar craiglyons avatar dependabot[bot] avatar djanowski avatar dstokes avatar dustyburwell avatar erithmetic avatar ferentchak avatar freedomben avatar gswalden avatar gzurbach avatar itayadler avatar jashmenn avatar jeremy-w avatar jeromegn avatar jtblin avatar killercup avatar krolow avatar nicsnoek avatar noircir avatar payabooya avatar pirxpilot avatar rajit avatar ruudud avatar s25g5d4 avatar toomanybees avatar torifat avatar zebulonj 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

node-replay's Issues

Doesn't handle binary data

Binary data files on windows don't work with node-replay. The images open fine when in record mode but are broken when in replay mode.

Replay as a proxy

To use this if I was testing an iOS app, would be nice to set it up as a proxy for that app's unit tests. Maybe in conjunction with hoxy?

Recording does not work with Wreck

Hi @assaf . Thanks for making this module. This is something I was looking for a long time. But I am trying to use it with wreck npm module (another popular HTTP request module) and the recording does not work. Wondering if you have any ideas? Below is my code:

const Wreck = require('wreck');
const replay = require('replay');
var callback = function(err, response, payload){
    console.log(err);
    console.log(payload); // converting the buffer to a string and logging
};
Wreck.get('https://www.example.com', callback);

The error is :

bash-3.2$ REPLAY=record node test.js 
{ Error: Payload stream closed prematurely
    at ProxyResponse.onResClose (/mocks/experiments/wreck_replay/node_modules/wreck/lib/index.js:383:32)
    at ProxyResponse.g (events.js:286:16)
    at emitNone (events.js:86:13)
    at ProxyResponse.emit (events.js:185:7)
    at ProxyResponse.<anonymous> (mocks/experiments/wreck_replay/node_modules/replay/lib/replay/proxy.js:163:22)
    at ProxyResponse.g (events.js:286:16)

request occasionally fires multiple end events

When using request the end events are sometimes fired multiple times. This is because request includes a fix for a bug in node core. request will fire an end when it see a close event if it hasn't yet seen an end event. Sometimes request is receiving the close event from node-replay first which causes it to fire an end event and then request receives the end event from node-replay and fires another end event.

A quick fix is disabling these lines of code but I don't know if that would have any unintended consequences.

I believe it only occurs on some requests because it's a race condition.

mode=record_new, like `cheat`, but records new tests.

Is it possible to add a replay mode similar to cheat, but when requests are not matched and it makes a request to the server, have it record that request?

Here's my scenario:
Say I've got a set of tests user_tests.js that I wrote who knows how long ago. Today, I'm adding some new tests to that file: after writing them, I run my tests with npm test, and my new tests fail:
Replay: POST http://foo.bar/users refused: not recording and no network access. Well duh, that's cool, I'll just switch to record mode. So I go ahead and run REPLAY=record npm test and suddenly I'm re-recording every request ever made... oops! Some of my tests are calls to twitter and I've just tweeted my love for carly rae jepson... oh well, I can delete that tweet.

There's a workaround, if you want...
Now I can work around it by specifically setting the replay mode to record before running that specific test and then set it back to replay afterwards, but that's a lot of leg work.

But what would be nice is...
What I'd like to be able to do is run REPLAY=cheat_and_record npm test and have it record all those new requests.

However, cheat_and_record is a pretty bad name: any suggestions here?

Recorded Requests don't Include Query String Paramters

E.g. http://example.com/query?yay=true and http://example.com/query?yay=false are both recorded to the same file with GET /query at the top.

Is this project active? I'm willing to write a pull request to fix this.

Replay seems to be eating requests without returning any response. Running the example just silently exits.

I slightly modified the example like this to make sure I was getting ANY response:

$ cat test.js 
assert = require("assert")
http = require("http")
replay = require("../lib/replay")

http.get({ hostname: "www.google.com", path: "" }, function(response) {
    console.log(response)
    response.body = "";
    response.on("data", function(chunk) {
        response.body = response.body + chunk;
    })
   response.on("end", function() {
        console.log("Got Something!");
   })
})

I get no response at all.

If I comment out replay = require("../lib/replay"), then I get the web reply I expect.

I've read the docs here http://documentup.com/assaf/node-replay, but I'm puzzled as to what's going on. Can anyone see the problem?

replay fails with 'request' library + timeout option

Hello all,

We're using request as our http client + replay to do some testing. However our tests fail as soon as we try to use "timeout" option (more details here)

To reproduce I modified example.js. Third test case fails with:

/Users/tadas/src/node-replay/example/test.js:29
  assert.equal(response.statusCode, 200);
                       ^
TypeError: Cannot read property 'statusCode' of undefined
    at Request._callback (/Users/tadas/src/node-replay/example/test.js:29:24)
    at self.callback (/Users/tadas/src/node-replay/node_modules/request/request.js:368:22)
    at Request.emit (events.js:95:17)
    at Object._onImmediate (/Users/tadas/src/node-replay/node_modules/request/request.js:986:16)
    at processImmediate [as _immediateCallback] (timers.js:354:15)

If anyone who knows internals of replay better could cast an eye on this that'd be great. I may be able to look at this some time later but cannot promise anything.. So here's at least the report.

Thanks!

request headers should be stringified before match comparison

Say you record a request like:

http.get({ ... , headers: {foo: 123, bar: null}}, function(response) {
  ...
})

Replay will record the integer and null literal headers. When they are deserialized for the replay, they will be strings. But the values they are compared against for matching purposes are not strings, so none of the recordings will match, and you'll get a "not recording and no network access".

Instead, replay should stringify all request headers before comparing them to the recorded values.

Allow regex in passThrough

I would like to record a 'request' call in my app which is a 'localhost' service:

app.js:

'use strict';

const express = require('express');
const request = require('superagent');

var app = express();

app.get('/hammer/version', function(req, res) {
    request
        .get('http://localhost:7777/geturl')
        .end(function(err, response) {
            console.log(response.body);
            res.status(200).json({
                version: '0.1.0',
                url: response.body.url
            });
        });
});

module.exports = app;

test.js:

/* global describe, it */
'use strict';

const request = require('supertest');
const app = require('./app.js');

var path = require('path');
const Replay = require('replay');

Replay.fixtures = __dirname + '/fixtures/replay';
// -> All localhost request are ignored :/ RegEx would work
Replay.passThrough('/hammer/*');

describe('Version test', function() {
    this.timeout(0);

    it('test version', function(done) {
        request(app)
            .get('/hammer/version')
            .expect(200, {
                url: "http://www.foobar.org",
                version: '0.1.0'
            })
            .end(function(err, res) {
                if (err) return done(err);
                done();
            });
    });
});

headers not stored correctly

I set:

Replay.headers.push(/.*/); so save ALL headers since we have quite a few with the API which don't conform to standards.

However, they're not stored correctly. For example:
WM_TENANT_ID: 0 is stored as wm_tenant_id:_ (underscore represents a blank space here).

Note two things:

  1. Capitalization is wrong.
  2. The zero is not stored.

jsdom XMLHttpRequest reports no headers

jsdom expects rawHeaders to be available. They are being generated internally but just not passed on. This can be fixed by adding rawHeaders: response.rawHeaders || [] to this block of code:

this.response = {
version: response.version || '1.1',
statusCode: response.statusCode && parseInt(response.statusCode, 10) || 200,
statusMessage: response.statusMessage || '',
headers: {},
body: response.body ? response.body.slice(0) : [],
trailers: {}
};

npm install replay fails on Windows

Hi there,

Even though this is for Windows, it is an easy fix! The fixture in the spec uses a fixture called example.com:3001 - on Windows, you can't have colons in the file name. Renaming it example.com will allow npm to install the module.

I would have done this in a pull request, but I'm not sure how you are running "example.com" on 3001 - I assume there is some sort of proxy, but it wasn't clear from the docs.

Any way, I hope that that isn't to big an issue to sort out.

Https requests are hanging

When trying to request the following url, the requests just hang:
When node-replay is disabled the requests work fine.

https://api.mailgun.net:443/v2/maxkferg.mailgun.org/messages.mime

I'm not sure if it is because of the :443 or the https prefix.

Uncaught Error: Protocol:https: not supported.

I'm trying to use node-replay to capture requests to an https endpoint, but I keep getting the following message:

Uncaught Error: Protocol:https: not supported.
  at exports.request (http.js:1840:11)
  at Object.HTTP.request (~/project/node_modules/replay/lib/replay/index.js:28:12)
  at Object.HTTPS.request (~/project/node_modules/replay/lib/replay/index.js:41:15)
  at Request.start (~/project/node_modules/request/request.js:708:30)
  at Request.end (~/project/node_modules/request/request.js:1405:28)
  at end (~/project/node_modules/request/request.js:433:16)
  at ~/project/node_modules/request/request.js:447:9
  at process._tickDomainCallback (node.js:459:13)

I was under the impression (#4, #18) that node-replay worked with https requests.

way to specify directory to store in dynamically

So I have an issue where two calls to the same URL return different result depending on state, e.g adding an item to a shopping cart and then getting the results from the shopping cart. I'm writing an API so I can't get around having to make the calls.

I've played around with setting the fixtures dir, but with the current implementation I can't change the fixtures dir on a test-by test case. It would be really nice if I could set the directory dynamically on a test-by-test basis somehow manually to deal with this problem.

Building tools with Replay

I'm making a simple HTTP proxy for use in Selenium UI tests. Replay is great because it provides an automated way to cache the responses from an external service. Ideally, though, I would not have to globally stub out Node's "http" module to do this--I would like to programmatically feed requests to Replay. This would make it easier for others to consume the tool (the "http" module will continue to function as normal in their environment).

@assaf: would you have any interest in extending the API to support this? I think it would involve:

  1. Exposing the Replay constructor and documenting the path to its module
  2. Defining a method to handle requests, possibly Replay#request(requestObject).
  3. Re-using Replay#request from the src/replay/index.coffee file

#3 is mostly an optimization to limit code duplication. It's based on my limited understanding of the project internals, so it might be wrong. #1 is technically simple, but it requires publishing a previously-private API, so I would understand any reluctance to do so.

Ignore .DS_Store Files

Took me a while to track down why my fixtures suddenly stopped being loaded. It was because a .DS_Store file got created by the Finder. Replay appears to read this file, see gibberish, and then generates a new fixture.

Can node-replay capture any internal API calls from a webpage

I understand that a HTTP.get() can be recorded and replayed using this module. What if I have an API call inside the url which returns a JSON file that app is using. I did not see that happening when I tried this module. The files that are recorded are either html output, never a JSON response of a GET or POST calls.. Anything I am missing?

When using proxy request, replay records (wrong) response but doesn't play it back

var replay  = require('replay');
var request = require('request');

request.get({
    uri: 'http://www.google.com/',
    proxy: 'http://proxy.somedomain.com:25800'
}, function (err, res, body) {
    // do stuff
});

As expected, this gives:

Replay: GET http://proxy.us-proxies.com/:25800http//www.google.com/ refused: not recording and no network access

So I turn on recording, and it creates a fixture. Great. Now I run it in replay mode, and I get the same refusal message again.

Furthermore, what it records as the response is not the response that the proxy server gives back from Google, but rather what you would get if you sent a request to the proxy directly -- on port 80, no less -- as if uri was set to http://proxy.somedomain.com.

'localhost' is not passed through

Hey,

I have just discovered, that the new version of this library does not handle requests to localhost correctly. These are being proxied and depending on the mode rejected.

I guess the reason for that is an incorrect use of the Set object in index.js

this._localhosts = new Set('localhost', '127.0.0.1', '::1');

This will actually create a set of l,o,c,a,h,s,t and make the condition this._localhosts.has(host) always fail, even if host is localhost.

Headers matched one way

I'm using node-replay to test caching. My use case is as follows:

  • Send request to remote API
  • Receive response, store Etag
  • Send the exact same request but include the header: If-None-Match: "Etag from previous response"
  • Verify that I receive a '304 Not modified'

Node replay treats the first request (without If-None-Match header) as if it were identical to the second request. That's because it iterates over the headers stored in the matcher and comparing them to their equivalents in the actual request being matched. This effectively ignores any extra headers in the request.
I believe it's a valid use case and a request with an additional header should be treated as an entirely different request. I had a go at it in a fork but have not yet been able to find a simple and elegant solution to this...

How to record repetitive requests without replaying them?

I need to capture a 429 (rate-limiting) response code from a 3rd party server for testing, so I want to keep firing off the same request and recording responses until I get one that has the 429 response code ... I don't want to replay anything. I want to fire off ... like 400 requests, same ones, record them all ... then grok through them to find the one that has a 429 response code for my test case reuse.

How can I do that?

Ignore parameters by name

Github API requests can contain access_token parameter which value got sensitive data.
I could remove or overwrite its value, however, then replay wouldn't get a hit
for the request anymore as it checks for this parameter, too.
How can I let replay ignore this parameter?

should not record requests to allowed hosts

There doesn't seem to be a way to configure replay to allow requests to certain hosts and not record them.

Request.ignore doesn't do what I want, because I need the requests to succeed.
Request.allow doesn't do what I want, because it still records requests and responses to the host in record mode.

IMO, hosts in Request.allow should never be recorded. This is what most people would expect I think.

For now I work around this by deleting the unwanted fixtures after recording.

does not allow testing with a String as the first parameter

Abstract

Node-Replay does not support a String as the first parameter of http.get, and never actually proxies requests where the first argument is a String.

Details

As per the node.js documentation around http.get, a URL string can be passed instead of an options object. Node.js then uses url.parse to separate this out as needed. Therefore the following code should work:

http.get('http://google.com')

Node-Replay does not support this, it assumes options is an object. If the properties cannot be found on the object it defaults to passing isLocalhost - e.g:

var options = 'http://google.com';
var hostname = options.hostname || (options.host && options.host.split(":")[0]) || "localhost"
console.log(hostname); // "localhost"

This means using http.get with a String as the first argument results in Node-Reply not proxying the request.

Solution

Detecting if the first argument is a String, and converting it to the expected object - e.g typeof options === 'string' ? url.parse(options) : options is the best solution. If you'd like I can create a PR for this, but I don't have time to do it today (with tests).

Replay different responses to same request?

In the README, you say that replay can be used to "Replay different responses to same request (great for testing error handling)". But I cannot figure out how to do this. Once something has been set up as the fixture for a request, there doesn't really seem to be a way to have another. Would you please explain how I can set it up to realize this feature?

Possible to use node-reply for integration testing?

I'm attempting to use node-replay in my integration tests.
For example, let's say I have test.js which requires api.js that makes calls to a http API. How would I use node-replay to replay those responses received in api.js.
Hope that makes sense... Thanks in advance.

supertest and node-replay don't play nicely together

I'm using supertest for some integration testing, and I'd like to use node-replay to record the external api requests/responses made by the server. However, when I turn off recording I see this:

     Error: GET http://127.0.0.1:4788/foo/bar refused: not recording and no network access
      at ProxyRequest.end (/Users/grant/src/blah/node_modules/replay/lib/replay/proxy.js:97:19)
      at process.startup.processNextTick.process._tickCallback (node.js:244:9)

From my understanding of node-replay, requests to 127.0.0.1 should be ignored, no? Looking at the tests, I see requests made to 127.0.0.1 handled properly. Sadly, supertest hard-codes(!) 127.0.0.1.

I'll see if I can't put together a simple test project that demonstrates the problem, but thought I'd post first to see if others had insight.

Documentation for generating fresh SSL keys

Please update the SSL key and cert in test/ssl, and document the steps required to do so. Tests are failing because the cert is expired.

With the expired keys:

1) Pass through ssl "before all" hook:
   Error: CERT_HAS_EXPIRED
    at SecurePair.<anonymous> (tls.js:1283:32)
    at SecurePair.EventEmitter.emit (events.js:92:17)
    at SecurePair.maybeInitFinished (tls.js:896:10)
    at CleartextStream.read [as _read] (tls.js:430:15)
    at CleartextStream.Readable.read (_stream_readable.js:304:10)
    at EncryptedStream.write [as _write] (tls.js:344:25)
    at doWrite (_stream_writable.js:211:10)
    at writeOrBuffer (_stream_writable.js:201:5)
    at EncryptedStream.Writable.write (_stream_writable.js:172:11)
    at write (_stream_readable.js:557:24)
    at flow (_stream_readable.js:566:7)
    at Socket.pipeOnReadable (_stream_readable.js:598:5)
    at Socket.EventEmitter.emit (events.js:92:17)
    at emitReadable_ (_stream_readable.js:392:10)
    at emitReadable (_stream_readable.js:388:5)
    at readableAddChunk (_stream_readable.js:150:9)
    at Socket.Readable.push (_stream_readable.js:113:10)
    at TCP.onread (net.js:511:21)

And with a self-signed keypair I just made:

1) Pass through ssl "before all" hook:
   Error: DEPTH_ZERO_SELF_SIGNED_CERT
    at SecurePair.<anonymous> (tls.js:1283:32)
    at SecurePair.EventEmitter.emit (events.js:92:17)
    at SecurePair.maybeInitFinished (tls.js:896:10)
    at CleartextStream.read [as _read] (tls.js:430:15)
    at CleartextStream.Readable.read (_stream_readable.js:304:10)
    at EncryptedStream.write [as _write] (tls.js:344:25)
    at doWrite (_stream_writable.js:211:10)
    at writeOrBuffer (_stream_writable.js:201:5)
    at EncryptedStream.Writable.write (_stream_writable.js:172:11)
    at write (_stream_readable.js:557:24)
    at flow (_stream_readable.js:566:7)
    at Socket.pipeOnReadable (_stream_readable.js:598:5)
    at Socket.EventEmitter.emit (events.js:92:17)
    at emitReadable_ (_stream_readable.js:392:10)
    at emitReadable (_stream_readable.js:388:5)
    at readableAddChunk (_stream_readable.js:150:9)
    at Socket.Readable.push (_stream_readable.js:113:10)
    at TCP.onread (net.js:511:21)

So I'm all out of ideas here without some additional documentation.

not working at all

I really want to use this module, but it is not working for me at all.
Changing the mode does nothing. As soon as it is included, all my requests just time out and do nothing.

  • I am using node v0.12.3
  • I am making https requests
  • I am using mocha and superagent

Trying to do some digging but maybe someone else knows what's up?

Mocha tests fail on master

I was attempting to modify this library in order to permit RegEx matching on the body. When I cloned it, however, I found that all the mocha tests fail. The most recent commit that I can get them to pass for is 1ee5c96, just after the test cases were converted to ES6 but just before the code base was converted to ES6. Is this accurate or am I not running this correctly? I'm running npm install, then gulp, then mocha.

fixtures file not creating

Hi I downloaded replay using npm install and at the top of my protractor tests in a beforeEach statement I included var replay = require("replay"). I then tried to run my tests with grunt protractor and expected to see them fail since they can't make any of the network calls to load the data needed in the tests...however the tests ran as if replay were not working. I then ran replay in record mode and no fixtures file was created.

Yesterday at least I knew replay was doing something since all my tests failed when I tried using it but today something is odd.

"TypeError: Cannot call method 'listeners' of undefined" when using mikeal's request

For some reason, I'm getting

TypeError: Cannot call method 'listeners' of undefined

when using node-replay with the latest request.

Trace is:

     TypeError: Cannot call method 'listeners' of undefined
      at /Users/jgn/projects/represent/node_modules/request/main.js:517:29
      at ProxyRequest.HTTP.request (/Users/jgn/projects/represent/node_modules/replay/lib/replay/index.js:25:14)
      at ProxyRequest.g (events.js:185:14)
      at ProxyRequest.EventEmitter.emit (events.js:88:17)
      at ProxyRequest.end (/Users/jgn/projects/represent/node_modules/replay/lib/replay/proxy.js:92:17)
      at process.startup.processNextTick.process._tickCallback (node.js:244:9)

Did node's http api change? Looks like request is expecting response.connection to be an EventEmitter (here: https://github.com/mikeal/request/blob/master/main.js#L517)

Any idea?

Disable Replay / restore HTTP functions

I use Replay to get started, while slowly converting web mocks to hand-coded objects via nock. Unfortunately they both modify HTTP, so they can't be run in the same suite. Any way to disable Replay and restore HTTP in an after() function?

Latency simulation

Is there any way to simulate slow responses? It would be extremely useful to test timeout behavior in REST clients.

Example for custom file name

In the readme you say The file name is a timestamp, but feel free to rename it to something more rescriptive.

However, I don't see where this is possible. I'm trying to use this within mocha tests and would like to explicitly set the filename so that I have control of the fixture content in a CI environment to use scrubbed data. The tests do not use request, however, the library that is under test wraps up request as needed by the library.

Support streaming recorded responses

As far as I can tell, reading recorded responses from the replay directory uses a readFileSync which invalidates the potential low memory consumption of apps built on top of streams. Providing an optional streaming interface (using fs.createReadStream) on top of the stored responses would allow network-less playback w/o requiring apps to load the entire response into memory before processing it.

Time permitting, i'll take a crack at this but it could be a while ;)

Query parameters ignored when saving fixtures

I have the following API queries for which I want to mock responses:

Despite this text in the node-replay readme:

All responses are stored as text files using the simplest format ever [โ€ฆ]

  • First comes the request path (including query string)

with REPLAY=record, each variant is not stored as a separate request file: I only get one file, set to the query http://wpapi.loc/wp-json/wp/v2/posts, and replaying the requests for the query string variants throws an error. Unless I can replay multiple responses from the same endpoint, based on query string, replay isn't going to do my application a lot of good.

Is there a way to get Replay to record responses inclusive of query strings?

Version details: Latest version of replay & superagent

TypeError on Node.js 6.2.2

It's happened in 2 projects when I tried to update to Node.js 6.2.2.
6.2.0 was fine.

TypeError: Cannot set property 'readingMore' of undefined
    at ProxyRequest.IncomingMessage (_http_incoming.js:28:35)
    at new ProxyRequest (/Users/spect/git/refme-dashboard/node_modules/replay/lib/replay/proxy.js:27:26)
    at Object.HTTPS.request (/Users/spect/git/refme-dashboard/node_modules/replay/lib/replay/index.js:69:13)
    at Request.request (/Users/spect/git/refme-dashboard/node_modules/superagent/lib/node/index.js:528:28)

Problem using node-replay with PhantomJS/selenium server

I've got a test starting a PhantomJS selenium-style server, with node-replay in record-mode and replay.ignore('127.0.0.1:4444');

I'm currently getting an error as follows when I run REPLAY=record mocha test.js:

Uncaught UnknownError: Missing Command Parameter - Request => {"headers":{"Connection":"keep-alive",
   "Host":"127.0.0.1:4444","accept":"application/json; charset=utf-8","content-length":"51",
   "content-type":"application/json;charset=UTF-8"},"httpVersion":"1.1","method":"POST",
   "url":"/session","urlParsed":{"anchor":"","query":"","file":"session","directory":"/","path":"/session",
   "relative":"/session","port":"","host":"","password":"","user":"","userInfo":"","authority":"",
   "protocol":"","source":"/session","queryKey":{},"chunks":["session"]}}

Which seems to be a selenium protocol error. If I run without node-replay, the test passes completely fine.

The same happens with REPLAY=cheat mocha test.js. Is it possible replay mutates the requests somehow?

I'm not familiar with the Selenium wire protocol so not really sure what the problem is.

Is it possible to include a method/mode to remove unused fixtures?

With time when the test cases grow and changes occurs, new fixtures gets recorded, this results in directory which is big in size and contains lot many fixtures that are not required. So is it possible to introduce a method which removes all unused fixtures. This method can be called after running the test cases, or better, a mode specifically designed for doing this task?

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.