mockttp icon indicating copy to clipboard operation
mockttp copied to clipboard

Feature Request: data as a function.

Open wachunei opened this issue 7 years ago • 4 comments

Hello,

I've been playing this morning with this library to write some tests, thanks for making it available on the first place 😄

I don't know if this already exists as a feature, but I'm looking to do this, I think a example would be better to understand:

const mockServer = require('mockttp').getLocal();

describe('Mockttp', () => {
  beforeEach(() => mockServer.start(8888));
  afterEach(() => mockServer.stop());

  it('can detect params', async () => {
    await mockServer
      .get('/resource/:id/nested')
      .thenJSON(200, (params) => ({ nested: [], resource: params.id }));

    const id = 3;
    const response = await fetch(`localhost:8888/resource/${id}/nested`);

    expect(response.data.resource).to.equal(id);
  });
});

Is this something done or you would like to be done 👀?

wachunei avatar Sep 05 '18 18:09 wachunei

Interesting! Right now, the best way to match the path with a regular expression instead of a string to match the request, and then use thenCallback, which passes the request details including the full URL to the callback, and your callback can match against that and do what it likes from there.

That should work for you for now. I'd be potentially open to a shorthand that made that a little easier, but I'm a little cautious about magic values in strings like :id there, particularly because that string could actually be a full URL (https://abc.com/def), so might well have colons in for protocol specifiers too, and it all gets a bit tricky.

What about if we exposed matching groups from the regex into thenCallback? That way you could do something like:

.get(/\/resource\/(\w+)\/nested/)
.thenCallback((request) => ({
	status: 200,
	json: { nested: [], resource: request.matchedGroups[0] }
}))

It's a bit awkward (though with named groups it gets marginally nicer), but more flexible. This way you can match only parts of a path segment, or combine wildcard path matching with this functionality. Regex syntax is a bit painful though... What do you think?

pimterry avatar Sep 06 '18 12:09 pimterry

I was thinking about using path-to-regexp as many other routers (sorry I don't link I'm on my phone)

Saludos.

-- Pedro Pablo Aste Kompen On Sep 6, 2018, 9:08 AM -0300, Tim Perry [email protected], wrote:

Interesting! Right now, the best way to match the path with a regular expression instead of a string to match the request, and then use thenCallback, which passes the request details including the full URL to the callback, and your callback can match against that and do what it likes from there. That should work for you for now. I'd be potentially open to a shorthand that made that a little easier, but I'm a little cautious about magic values in strings like :id there, particularly because that string could actually be a full URL (https://abc.com/def), so might well have colons in for protocol specifiers too, and it all gets a bit tricky. What about if we exposed matching groups from the regex into thenCallback? That way you could do something like: .get(//resource/(\w+)/nested/) .thenCallback((request) => ({ status: 200, json: { nested: [], resource: request.matchedGroups[0] } })) It's a bit awkward (though with named groups it gets marginally nicer), but more flexible. This way you can match only parts of a path segment, or combine wildcard path matching with this functionality. Regex syntax is a bit painful though... What do you think? — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

wachunei avatar Sep 06 '18 12:09 wachunei

Yep, so that's where it gets tricky, because that argument might be a path, or it might be a full URL. To detect which one it is so that you only pass the path part to path-to-regexp, you need to parse the full URL first. I suspect though lots of URL parsers will fail to parse it, because you're not allowed to have a : within a path like that, so you're stuck.

There might be more relaxed parsers, and feel free to try, but I worry that you might have to build all the parsing yourself from scratch, and that doesn't sound like a good idea.

pimterry avatar Sep 06 '18 13:09 pimterry

Oh I see, right now I can think of URIjs to pre-parse but I'm still on my phone so I could check later. Actually I could write some tests and figure it out.

Saludos.

-- Pedro Pablo Aste Kompen On Sep 6, 2018, 10:07 AM -0300, Tim Perry [email protected], wrote:

Yep, so that's where it gets tricky, because that argument might be a path, or it might be a full URL. To detect which one it is so that you only pass the path part to path-to-regexp, you need to parse the full URL first. I suspect though lots of URL parsers will fail to parse it, because you're not allowed to have a : within a path like that, so you're stuck. There might be more relaxed parsers, and feel free to try, but I worry that you might have to build all the parsing yourself from scratch, and that doesn't sound like a good idea. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

wachunei avatar Sep 06 '18 13:09 wachunei