Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide request url matching #1

Closed
kettanaito opened this issue Nov 13, 2018 · 7 comments
Closed

Provide request url matching #1

kettanaito opened this issue Nov 13, 2018 · 7 comments

Comments

@kettanaito
Copy link
Member

kettanaito commented Nov 13, 2018

What:

I propose to provide a smart request url matching.

https://github.com/kettanaito/msw/blob/a1196004c390d115d29941de405d9db571357107/serviceWorker.js#L38

Why:

To support placeholders, params, and other parts of url:

How

https://domain.com/shop/:shopId

To match all the following:

https://domain.com/shop/foo // { shopId: "foo" }
https://domain.com/shop/bar // { shopId: "bar" }

We can also parse the params and expose them within the req reference for handler(req) to access in the mocking handler.

The challenge here is that the logic happens inside a Service Worker, thus it should be done without requiring any package.

@bebraw
Copy link

bebraw commented Nov 13, 2018

Something like url-matcher can likely handle the matching part. Simple after that.

@kettanaito
Copy link
Member Author

kettanaito commented Nov 13, 2018

@bebraw Thing is, it is not enough to simply determine if a string matches a given mask. Here's the draft unit case of how this should work:

const parsedRoute = parseRoute(
  'http://foo.com/user/:username/:messageId',
  'http://foo.com/user/bebraw/21'
)

expect(parsedRoute).toEqual({
  params: {
    username: 'bebraw',
    messageId: '21'
  }
})

So the params can be inserted into the req reference and passed into the mocking function. Afaik, there is no params/query parsing on the Request instance by default.

@bebraw
Copy link

bebraw commented Nov 13, 2018

Yeah, I see. It's a bit more complicated.

@kettanaito
Copy link
Member Author

@bebraw I have a stupid idea to gather the map of param names and their indexes, and then reduce the route string into the map of params.

@bebraw
Copy link

bebraw commented Nov 13, 2018

Worth a go.

@kettanaito
Copy link
Member Author

kettanaito commented Nov 14, 2018

So, there is a small function that check if a route matches the mask, and gathers its params. It's limited, but works.

function parseRoute(mask, route) {
  let paramsList = []
  const replacedMask = mask.replace(/:(\w+)/g, (a, b) => {
    paramsList.push(b)
    return '(\\w+)'
  })

  const match = new RegExp(replacedMask).exec(route)
  const params = match && match.slice(1, match.length).reduce((acc, paramValue, index) => {
    const paramName = paramsList[index]
    return Object.assign(acc, {
      [paramName]: paramValue
    })
  }, {})

  return {
    url: route,
    matches: !!match,
    params,
  }
}

Update: I've integrated this to the Service Worker right now and it's great so far.

@kettanaito
Copy link
Member Author

The current implementation looks sufficient at the moment, closing.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants