Giter Club home page Giter Club logo

talkback's People

Contributors

brandonc avatar dependabot[bot] avatar halilb avatar ijpiantanida avatar mefellows avatar rmjohnson avatar rmtsrc avatar sarayourfriend avatar sebflipper avatar simonneutert avatar unstubbable avatar vacuum-car 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

talkback's Issues

Multiple hosts support?

Hello,

I couldn't find in docs anything related to multiple hosts. My ideal would be to have ability to provide options as array. Like this:

const opts = {
host: ['http://example.com', 'http://example2.com'],
record: talkback.Options.RecordMode.NEW,
port: 5544,
path: "./offline-tapes"
};

Is this already possible or is it something I need to introduce to the project via PR?

https option

Can we make it possible to use https instead of http. Perhaps with options: https, key and cert?

Greetings

Christian

Match headers

Hello,

First of all, thanks for the great tool, fast to onboard.
I experience a problem of matching. I have some user session cookies in headers of my requests. I would like to ignore them (and maybe other stuffs in headers, like dates), because I can't reuse the recorded requests.
I use talkback to mock my API for development or load test. Not to test the features. So the session cookies are not usefull.

Is it possible to add a headerMatcher ?

Regards

Feature Request: Option to always record tape for incoming reqeuest

Hello!

I discovered Talkback yesterday and really dig the simplicity of its API and that the tape format is easily human readable. I'm working on adding new testing infrastructure to an existing large system, and see this as a valuable tool to transparently sit between components and record activity between them for later analysis and playback (via another tool, as I don't think Talkback supports arbitrary tape replay right now)

However, Talkback's behavior of replaying tapes matching an incoming request subverts this use-case. Consider the following hypothetical request sequence:

  • GET /comment: Get all comments
  • POST /comment: Create a new comment
  • GET /foo: Get all comments again, this time with the newly created one

In this use-case, we expect the second GET call to return a different response from the first, but Talkback will only record the first GET request in this sequence and replay it for the second. This is problematic when situating Talkback as a transparent middle-man between two existing system components.

So, I propose an option that allows the "always replay" behavior to be disabled, and thereby enabling this use-case.

Also, I admit that it's entirely possible that there exists a better tool for this use-case and that it doesn't make sense to include this behavior in Talkback. I'm definitely open to alternatives, but my searching around the ecosystem kept leading me back here. If anyone knows of such a better tool, please let me know! 😁

Modify saved response during replay

My app sets a non-deterministic request id which the response has to match so I need to update the tape to include the request id.

Can we add a new option that allows the outbound tape response to be edited bodyUpdater.

const opts = {
  host: "http://localhost:9001",
  port: 9000,
  bodyMatcher: (tape, req) => {  /** stripe out request id */},
  bodyUpdater: (tape, req) => { /** get new request id from req and replace old request id instances from the tape */}
}

Error when trying to connect to an https with self-signed certificate

On my dev environment, I'm using openshift with a self-signed certificate (https), when trying to use this tool I get the following error: "reason: self signed certificate in certificate chain"

Is there a way to allow self-signed certificates?

{ url: '/api/auth/info',
  headers:
   { 'x-forwarded-host': 'localhost:3000',
     'x-forwarded-proto': 'http',
     'x-forwarded-port': '3000',
     'x-forwarded-for': '127.0.0.1',
     cookie:
      '_ga=GA1.1.1514412781.1557421740; Webstorm-a9376004=b9c98f11-f6b4-4bb3-84c3-0983d04fd04e; _gid=GA1.1.1489284077.1565034839',
     'accept-language': 'en,en-US;q=0.9,es-419;q=0.8,es;q=0.7',
     'accept-encoding': 'gzip, deflate, br',
     referer: 'http://localhost:3000/',
     'content-type': 'application/json;charset=utf-8',
     'user-agent':
      'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36',
     'x-auth-type-kiali-ui': '1',
     accept: 'application/json, text/plain, */*',
     connection: 'close',
     host: 'localhost:3030' } }
Making real request to https://kiali-istio-system.127.0.0.1.nip.io/api/auth/info
Error handling request { FetchError: request to https://kiali-istio-system.127.0.0.1.nip.io/api/auth/info failed, reason: self signed certificate in certificate chain
    at ClientRequest.<anonymous> (/home/josejulio/Documentos/redhat/kiali/kiali-mock-server/node_modules/node-fetch/lib/index.js:1455:11)
    at ClientRequest.emit (events.js:182:13)
    at TLSSocket.socketErrorListener (_http_client.js:392:9)
    at TLSSocket.emit (events.js:182:13)
    at emitErrorNT (internal/streams/destroy.js:82:8)
    at emitErrorAndCloseNT (internal/streams/destroy.js:50:3)
    at process._tickCallback (internal/process/next_tick.js:63:19)
  message:
   'request to https://kiali-istio-system.127.0.0.1.nip.io/api/auth/info failed, reason: self signed certificate in certificate chain',
  type: 'system',
  errno: 'SELF_SIGNED_CERT_IN_CHAIN',
  code: 'SELF_SIGNED_CERT_IN_CHAIN' }

New feature: Ignore parts of the url

The problem:

We have urls that are created from previous server responses like:
http://localhost:8081/payments/${paymentId}/transactions/${transactionId}/import
where http://localhost:8080 is the host key in the options object and /${paymentId}/transactions/${transactionId}/import is the url key in the recorded tapes.

As far as I understand, Talkback uses the url key when matching tapes. This will force a new call to the real server for every new variable value.

A solution:

A solution is to introduce a url/pathname matcher property, where one could replace the variables with fixed values. I guess its much the same solution as you did with the bodyMatcher.

WebSocket Support

Any way to use this to record an replay for websocket interactions?

Internal 500 error when prettying JSON response

Given following:

var talkback = require("talkback");

var server = talkback({
  host: "https://jsonplaceholder.typicode.com",
  path: __dirname + "/tapes",
  port: 3002,
  debug: true
});

server.start();

I am getting response 500, when requesting localhost:3002/todos/1
with header: Content-Type: application/json.

Removing this method fixes the problem.

I don't understand why this is necessary.

How to decode the body in request part of the tape?

Hi Guys,

I would appreciate to know whats the logic behind encoded body parts of the request?
What I usually get as a recorded tape something like this;

	req: {
		headers: {},
		url: "/graphql",
		method: "POST",
		body: "ewogICJxdWVyeSI6ICJcblx0XHRcdFx0cXVlcnk.......",
	},

I hope you agree that any test setup rather likes it to be readable and understandable and it is the usual case that you use talkbak in development. For that reason it would be nice to know whats the philosophy behind encoding and how I can disable that.

I tried to understand the logic inside the talkback, but I am sure at least the author can say in one shot what is the reasonable way to approach that.
Here is what I found in the talkback source

// export const jsonTypes = [
// 	equals("application/json"),
// 	equals("application/x-amz-json-1.0"),
// 	equals("application/x-amz-json-1.1"),
// 	(contentType: string) => contentType.startsWith("application/") && contentType.endsWith("+json"),
// ];

// const humanReadableContentTypes = [
// 	equals("application/javascript"),
// 	equals("text/css"),
// 	equals("text/html"),
// 	equals("text/javascript"),
// 	equals("text/plain"),
// 	...jsonTypes,
// ];


// some logic in talkback expecting content-encoding is not set or it has the value "identity"

// so I should make sure in my FE code that I have a header like this one:
// request headers { headers: { "content-encoding": "identity" } }

The docu is not really mentioning it either.

Thanks a lot in advance, and many thanks for creating talkback its a rocket for me in any project.

Regards...

Flag to sort the request body by key names

Possibly Covered In Issue #7

Your proposal on how to handle partial body matching might also cover this issue. As one could maybe supply a deep match or body sorting function.

Problem

During some readability refactoring I wanted to sort some lines of code alphabetically, but because these were setting values for a request payload, it caused a cache miss in Talkback.

What I assume is the issue here is the payload object is unsorted when stringified. Which probably is in everyones interest for most situations in a performance perspective. But here it causes a cache miss for equal data with different ordering.

Working around the issue is no worse than rebuilding the Talkback request-response pair, but it may be tedious for bigger rounds of refactoring.

Proposal

A configuration flag for choosing to sort the body by key names. Opting for a flag as It will undoubtedly be a performance hit.

Flag Name Value Description Default
sortRequestBody Boolean Whether or not to sort the request body before building a cache. This removes the need for specific ordering in request payloads. false

Name of the talkback server in the summary

When running our tests we are starting 10 talkback servers, one for each of the different services our app is accessing. When the test runner terminates, all talkback servers reports their individual exit summary.

It would have been nice to distinguish the different exit summaries.
What if a talkback server can be given a name in its options, which them can be printed in the SUMMARY heading if present?

Example:

===== SUMMARY Customer server =====
Unused tapes:
- GET_customers_by_customerNumber.json5
- PUT_change_telephoneNumber_for_newly_made_customer.json5
===== SUMMARY Messaging server =====
===== SUMMARY Sales server =====
===== SUMMARY Order server =====
Unused tapes:
- UseCase-1_13_pay.json5
- UseCase-1_14_issue-tickets.json5
- UseCase-1_15_order-overview.json5

Multiple headers in response with the same name

Hi,

I'm trying to mock a response with multiple "Set-Cookies" header. As I saw, only the last 'Set-Cookies' entry in the file gets sent in the response. So instead of e.g. 5 Set-Cookies header, I get only one. Can this be a bug, or do I need to address this in some special way in the json5 file?

Thanks,
Sandor

Potential Feature Request: Consider only specific headers?

Hi @ijpiantanida,

many thanks for you this fantastic library, I used it in several projects. It is the core of my new testing philosophy that prefers integrative testing.

One problem I always have though:

The headers as part of the key inside the request always differ and consume time to figure out.
In the most cases I end up excluding almost all headers at the end, one by one. Specifically on CI environments a list of complete new headers additionally comes up, so it needs one more config with some dev ops guy.

So how about introducing a list of NOT ignored headers (e.g. considerOnlyHeaders) , basically the negation of the ignoreHeaders list. All other headers will be ignored?

By having that you would reduce the last complexity by setting up a new project with that and make it more transparent what is the actual comparison key for each tape. This can be an extra config not touching all the previous users with this feature.

So what do you think, would that make sense?

When starting multiple servers the logging does not use the server name provided in options

I start multiple Talkback servers in the same Node script, each handling the requests to a specific backend server.

The code looks something like this:

const startTalkbackServer = (serverName: string) => {
  const options = {
    name: serverName,
    host: config.get<string>(`${serverName}.talkbackUrl`),
    port: config.get<string>(`${serverName}.talkbackPort`),
    path: `./talkback/cached_responses/${serverName}`,
    // ...
  };

  const server = talkback(options);
  server.start(() => {
    console.log(`Talkback server started on http://localhost:${options.port} for ${options.host} with tapes at ${options.path}`);
  });
};

['accounts', 'customers'].forEach(startTalkbackServer);

This works very well. The only issue we have with this, is that the log output from each of the servers does not reflect the server name provided in the options. The log output from both servers have the same name in the log line. This is always the name of the last server started.

For example when the the summary is being printed from these two servers, it looks like this:

[talkback] 2022-06-23T07:55:49.200Z [customers] [INFO] ===== SUMMARY =====
...
[talkback] 2022-06-23T07:55:49.300Z [customers] [INFO] ===== SUMMARY =====
...

Any idea why this is happening?

UTF-8 characters in response returns malformed data

For example having the following setup and tapes:

index.js

const talkback = require("talkback");

const opts = {
  host: "https://example.com",
};
const server = talkback(opts);
server.start(() => console.log("Talkback Started"));

tapes/quotes.json5

{
    meta: {
        createdAt: '2019-03-19T22:03:41.814Z',
        host: 'https://example.com',
        resHumanReadable: true,
    },
    req: {
        url: '/test.json',
        method: 'GET',
        headers: {
            accept: '*/*',
            'user-agent': 'curl',
        },
        body: '',
    },
    res: {
        status: 200,
        headers: {
            'content-type': [
                'application/json; charset=UTF-8',
            ],
            date: [
                'Tue, 19 Mar 2019 22:03:42 GMT',
            ],
            expires: [
                'Tue, 26 Mar 2019 22:03:42 GMT',
            ],
            'last-modified': [
                'Tue, 19 Mar 2019 22:00:27 GMT',
            ],
            'content-length': [
                '46',
            ],
            connection: [
                'close',
            ],
        },
        body: {
            words: 'in special “quotes” break',
        },
    },
}

node index.js

curl -v -H 'User-Agent: curl' http://localhost:8080/test.json

Returns

* Excess found in a non pipelined read: excess = 4, size = 42, maxdownload = 42, bytecount = 0

{
  "words": "in special “quotes” brea

tapes/emojis.json5

{
    meta: {
        createdAt: '2019-03-19T22:03:41.814Z',
        host: 'https://example.com',
        resHumanReadable: true,
    },
    req: {
        url: '/test2.json',
        method: 'GET',
        headers: {
            accept: '*/*',
            'user-agent': 'curl',
        },
        body: '',
    },
    res: {
        status: 200,
        headers: {
            'content-type': [
                'application/json; charset=UTF-8',
            ],
            date: [
                'Tue, 19 Mar 2019 22:03:42 GMT',
            ],
            expires: [
                'Tue, 26 Mar 2019 22:03:42 GMT',
            ],
            'last-modified': [
                'Tue, 19 Mar 2019 22:00:27 GMT',
            ],
            'content-length': [
                '33',
            ],
            connection: [
                'close',
            ],
        },
        body: {
            emojis: 'also 😢 break',
        },
    },
}

curl -v -H 'User-Agent: curl' http://localhost:8080/test2.json

Returns

* Excess found in a non pipelined read: excess = 2, size = 31, maxdownload = 31, bytecount = 0

{
  "emojis": "also 😢 break"

Notice how the response is malformed and missing the closing brackets and objects.

A workaround is to remove the response content-length.

Disable header matching or provide a matcher

I've been using nock for a while and tried to migrate to your library.
Much better, easier, great job!

They only issue we have is that our scraping axios client is randomising headers (user agent, etc) on each request. Thus the requests never get matched. Ignore headers is not an option, because there are over 20 headers that may or may not be randomised. Is it possible to provide header matcher function or disabled header matching all-together.

FYI https://github.com/nock/nock#enable_reqheaders_recording-option
Nock does not bother matching the recordings by headers by default, because it brings a lot of similar issues....

Preserving the order of requests for each tests

I have used VCR gem in ruby before and it makes it seemless by creating one tape for each test which can be pointed to after the recording is done. It also goes down the requests in the order it receives during recording. It might be more opinionated, but it makes for a more repeatable integration test.

I am using selenium-webdriver with talkback to record the requests and playback in DISABLED mode to repeat application behavior. The issue is that if the same requests are being made with different responses, only the first one recorded is played back. In my scenario, I have an empty body response in the first response, and then a non-empty response after an action is taken on the webpage. I can certainly deleted the earlier tape with the empty response, but that wouldn't reflect realistic integration testing which talkback intends to solve.

An example I would like to use is adding to cart functionality. I would like to take the user through adding a product to cart by adding something from the page. At the first the cart is empty which means the response was empty, and then the user adds something to the cart which means the response is filled with a product object. This wouldn't precisely reflect the order of actions by the user in talkback.

It's possible I maybe overlooking something here. I look forward to your response.

Logo for talkback

Hi,

Talkback deserves love ;-) .

So I created some logos for free, if you like one feel free to use it. Sorry I am just a software dev not a design guy.

talk_1
talk_2
talk_3
talk_4
talk_5

bug: tapes aren't recorded with human readable body

Hello there 👋
First of all thanks for the effort you have put into this project. We have been using it to mock our API, and its flexibility is key.

I have a bug to report tho, and I believe I found the culprit.
The issue is that it isn't saving the tapes in human-readable form, which makes it a bit harder to debug them.

The issue is related to the case sensitivity of the content-type headers matcher (here) which I believe should be case insensitive.

For instance, our SDK uses the following request to communicate with the API:

  return api
    .request(`checkouts/${checkoutId}`, {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(formattedPayload),
    });

And that causes the tapes to be recorded like:

        body: 'ewogICJwYXltZW50X3R5cGUiOiAiYmFu...(content)',

How to reproduce

Make a request using the following content type format:

const talkbackURL = "http://localhost:3030"
fetch(talkbackURL, {
  headers: {
      'Content-Type': 'application/json'
   },
   body: JSON.stringify({"foo": "bar"}),
}).then(console.log)

Check the generated tape

Expected

  • Human readable body containing {"foo": "bar"}

Outcome

  • Encoded body

Suggested fix

When checking human-readable content type, ignore the case

// https://github.dev/ijpiantanida/talkback/blob/main/src/utils/headers.ts
static read(headers: any, headerName: string) {
    const caseInsensitiveKey = Object.key(headers)
         .find(h => h.toLowerCase() === headerName.toLowerCase())
    const value = headers[caseInsensitiveKey];
    if (Array.isArray(value)) {
      return value[0];
    } else {
      return value;
    }
  }```

Feature Request: Add a RecordMode.ALWAYS option

The new RecordMode is great! I especially like the ability to specify it per-request.

An additional use case for the new RecordMode would be an ALWAYS mode. In other words, a new tape is created with a request and response, whether or not a matching tape exists.

An example where this could be useful is this:

  • Service A calls Service B with GET /serviceB/info, no headers, no body
    • Initial response is 404/Not Found, because Service B is not yet running
  • Service A calls Service B again, and Service B is now up and running, and should return some good 'info'
  • Service A calls Service B again, and 'info' has changed to something I really don't want to make a tape out of

If I use RecordMode.New, the 404 will be returned forever, because the initial tape was made from the bad response, and then re-used

If I use RecordMode.Overwrite, I lose the middle tape, which had the good 'info'

If I use RecordMode.Disabled, I don't get a tape at all

With RecordMode.Always, I'll get all three tapes - then I can keep the tape I like, change over to RecordMode.Disabled, and re-run

Thoughts/opinions? I'd be happy to do a PR on this if you're interested and don't have time

Ability to modify req before making request ?

I have a situation where I want to store human readable content but I cannot do that because my browser always send 'accept-encoding': 'gzip, deflate, br' and it will be passed to backend server as well and my response body always end up base64 encoded.

I tried using chrome extension to remove 'accept-encoding from headers. Server then returns plain text and talkback also store response body in json. But this is not good when we work as a team. I think there should be a way to handle this kind of situation when we setting up talkback server.

Thanks for making talkback I really like it.

Partial body matching, possibly with Regex

I could give the following a try and make a PR if you think the it sounds like a worthwhile undertaking, @ijpiantanida.

Our problem

My team and I have often found that a request body contains some piece of ever-changing data, e.g. a date or timestamp. Consequently, Talkback is unable to serve a cached response for the request the next time we run our tests.

The new ignore body option partially solves our problem: It works fine when we want to cache just one response for a given URL. But there are some URLs for which we need to cache two or more responses and serve them based on differing characteristics of the bodies. (This is especially true for GraphQL-endpoints, where the body is the only thing that matters and we may have hundreds of different bodies.) Ignore body is not of much help to us in these situations.

Proposed solution

We discussed this in my team. Our best idea was to giving Talkback-users the option of adding a reqBodyIsRegex field to the meta-object in the cached response file, signifying that the request body is to be interpreted as a regular expression (requiring the author to convert the string to a regex). If any request body matches the regex, the cached response is served, exactly as stored. (Regex capturing groups could be used to adapt responses in the future, but I think this should not be in the first version of this.)

{
    meta: {
        createdAt: "2018-02-16T14:51:35.972Z",
        host: "http://example.com/",
        resHumanReadable: true,
        reqBodyIsRegex: true,
    },
    req: {
        body: 'Your body as a regex here. \(You would probably have to escape parentheses and stuff, but exactly how, remains to be seen\)'
    }
    ...
}

Matching priority

My thoughts are that exact matching will have priority over regex-matching. I do not have any ideas about how to tie-break between competing regexes, but my guess is there's either no solution or some really good, pre-existing solution.

New cached responses generated for identical request

Talkback keeps generating new cached responses after server restart even though the requests are identical. I thought the expected behaviour was that identical requests would cause the cached response to be returned.

screen shot 2018-05-02 at 12 49 38

I'm guessing differences in meta and res shouldn't cause a new cached response to be generated?

How to stop the server on CI?

Hi,

first: thank you so much for this awesome project! It rocks.

I have a simple case.

I start talk back in CI than I run the tests, and now I need to stop it somehow.
I see localServer.stop() in the doc but, it implies that the script that is tarting the server is somehow informed from outside that tests are done running.

A separate node script just to call localServer.stop(), fails, since the server is not initialized in this context and its not a singleton as it looks like. What should I do?

Basically you always need it if you want your server and tests to run as one command and you dont want to deal with two terminals.

I think this is a very common situation and worth mentioning.

Thanks in advance.

Denis.

Modify real request response to support Location header

The use of a Location header seems unsupported in Talkback.

I have tried to use the responseDecorator to alter the Location header that is stored in the tape, but since the response when no tape is found is from the real server, the client will follow that URL instead of requesting Talkback. This results in no tapes being stored for the requests that follows the Location header. In order for the client to request Talkback when receiving a Location header, Talkback would need to alter the Location header before responding to the client even when no tapes are found.

The solution seems trivial after looking at src/request-handler.js, and I would be more than willing to create a PR for this functionality.

Requests fail on Node v15.2.1

Hello,

I've started using Node v15.2.1 with talkback and discovered my simple requests are failing with it.

Here is the stack trace:

Error handling request TypeError: Cannot read property 'content-encoding' of undefined
at Function.Headers.read (/Users/halil/thanx/talkback/src/utils/headers.ts:2:434)
at ContentEncoding.contentEncoding (/Users/halil/thanx/talkback/src/utils/content-encoding.ts:2:7364)
at ContentEncoding.isUncompressed (/Users/halil/thanx/talkback/src/utils/content-encoding.ts:2:6802)
at Tape.normalizeBody (/Users/halil/thanx/talkback/src/tape.ts:3:2493)
at new Tape (/Users/halil/thanx/talkback/src/tape.ts:3:31)
at RequestHandler. (/Users/halil/thanx/talkback/src/request-handler.ts:2:10789)
at step (/Users/halil/thanx/talkback/src/request-handler.ts:2:8237)
at Object.next (/Users/halil/thanx/talkback/src/request-handler.ts:2:5187)
at /Users/halil/thanx/talkback/src/request-handler.ts:2:4300
at new Promise ()
at __awaiter (/Users/halil/thanx/talkback/src/request-handler.ts:2:3473)
at RequestHandler.handle (/Users/halil/thanx/talkback/src/request-handler.ts:2:10024)
at TalkbackServer. (/Users/halil/thanx/talkback/src/server.ts:3:95)
at step (/Users/halil/thanx/talkback/src/server.ts:2:8450)
at Object.next (/Users/halil/thanx/talkback/src/server.ts:2:5314)
at /Users/halil/thanx/talkback/src/server.ts:2:4406
at new Promise ()
at __awaiter (/Users/halil/thanx/talkback/src/server.ts:2:3561)
at IncomingMessage. (/Users/halil/thanx/talkback/src/server.ts:2:10702)

Here is my request in curl format:

curl --request GET \
  --url http://localhost:3000/apps/crew \
  --header 'Content-Type: application/json'

Also, 16 tests are failing in the talkback repository when I run them with Node 15.2.1.

Key order matters when comparing requests

I've experienced problems with requests not being served when their key order changes. I have a PR coming up which fixes this; just wanted to make the issue to have something to tag it onto.

Numbering can cause errors if previous tape was deleted

so by default the tapes get named unnamed-<number>.json5
if you have a few tapes and you haven't manually renamed them and you delete one from the middle. example:

unnamed-1.json5
unnamed-2.json5
(deleted tape because it became unused)
unnamed-4.json5

the default numbering will calculate that there are currently 3 tapes and the next tape should be saved at unnamed-4.json5 which will overwrite the previous tape.

Suggestion, switch to a different naming convention that is resilient to this...
I will submit a PR shortly, it will likely mean a breaking change to the signature of the tapeNameGenerator function.

Feature / Idea(s): Expose lower level APIs

First off, thank you for the amazing work @ijpiantanida, picking up from where yakbak left off and expanding on it was no small venture, so thank you.

I'm having amazing success with talkback. I'm integrating it into a stack that includes jest and puppeteer via jest-puppeteer.

Using jest and puppeteer I'm able to run my app in an actual browser, headlessly, and write jest tests against user flows to create a complete set of integration tests while having all the api requests proxy through talkback. This is in an early stage, but looks incredibly promising.

Feature Request / Idea:

puppeteer provides the ability to intercept http requests.

If talkback exposed some of the lower level apis like RequestHandler and OptionsFactory this could open up some incredible possibilities.

Using puppeteer's intercept functionality in conjunction with talkbacks tape recording functionality exposed via new apis without the need to create a whole new server could be extremely powerful.

Imagine it, having completely encapsulated full feature user flow integration tests run in a single node process. This aligns very strongly with your testing requirements from your great blog post.

As you can tell I'm super excited about these ideas and tooling possibilities.

In summary, again THANK YOU for your amazing work, and please let me know your thoughts/concerns. I'd love to explore making PRs where I can if this is something you're interested in.


Additional Idea: Talkback Middleware

Was additionally thinking talkback could expose a "middleware", which could help users who may already have a server, but still want to benefit from talkback's functionality without needing to make a whole new server?

const talkbackMiddleware = new talkback.middleware(opts);

app.use('/api', talkbackMiddleware)

TapeMatchers doesn't consider difference in protocol

Scenario

  1. Make a request to http://github.com and set options.record to talkback.Options.RecordMode.NEW
  2. Make another request to https://github.com and set options.record to talkback.Options.RecordMode.NEW

After 1. Talkback tries to load a tape, but there is no tape, so it creates one after sending the request to the original server. The response is a redirect to https://github.com.

After 2. Talkback loads existing tapes, and matches with tape created for 1. The request itself fails and no other tape will get created.

The root cause seems to be Talkback storing URL's path as URL in the tapes:

{
        headers: { ... },
        url: '/',
        method: 'GET',
        body: '',
}

And the TapeMatcher compares the url part which are same in HTTPS and HTTP cases.

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.