admin管理员组

文章数量:1122826

I have a single page application running in http://localhost:3001 and I have set the baseUrl as such.

Now, I would like to intercept all the external calls, so the ones going elsewhere than localhost:3001. How do I write this kind of single intercept in Cypress? Or am I doing this somehow "wrong" way around, design-wise?

I have tried following intercepts, but they all result in intercepting the http://localhost:3001/_nuxt files etc.

    cy.intercept("**!(localhost:3001)*", (req) => {
    cy.intercept("**!(localhost:3001)**", (req) => {
    cy.intercept(/^((?!http:\/\/localhost:3001).+)$/, (req) => {
    cy.intercept({ url: /^((?!.*localhost:3001).+)$/ }, (req) => {

The wacky part is that, the regex /^((?!.*localhost:3001).+)$/ is correct. It does not match the localhost files.

/^((?!.*localhost:3001).+)$/.exec("http://localhost:3001/_nuxt/components/Component.vue") => null

as it should be, and then

/^((?!.*localhost:3001).+)$/.exec(";)
(2) ['', '', index: 0, input: '', groups: undefined]

So, is Cypress intercept doing something more than just a plain regex exec or am I missing something obvious out here?

I have a single page application running in http://localhost:3001 and I have set the baseUrl as such.

Now, I would like to intercept all the external calls, so the ones going elsewhere than localhost:3001. How do I write this kind of single intercept in Cypress? Or am I doing this somehow "wrong" way around, design-wise?

I have tried following intercepts, but they all result in intercepting the http://localhost:3001/_nuxt files etc.

    cy.intercept("**!(localhost:3001)*", (req) => {
    cy.intercept("**!(localhost:3001)**", (req) => {
    cy.intercept(/^((?!http:\/\/localhost:3001).+)$/, (req) => {
    cy.intercept({ url: /^((?!.*localhost:3001).+)$/ }, (req) => {

The wacky part is that, the regex /^((?!.*localhost:3001).+)$/ is correct. It does not match the localhost files.

/^((?!.*localhost:3001).+)$/.exec("http://localhost:3001/_nuxt/components/Component.vue") => null

as it should be, and then

/^((?!.*localhost:3001).+)$/.exec("https://www.example.com")
(2) ['https://www.example.com', 'https://www.example.com', index: 0, input: 'https://www.example.com', groups: undefined]

So, is Cypress intercept doing something more than just a plain regex exec or am I missing something obvious out here?

Share Improve this question edited Nov 23, 2024 at 1:17 Aladin Spaz 9,2981 gold badge18 silver badges38 bronze badges asked Nov 22, 2024 at 14:23 Juho RutilaJuho Rutila 2,4581 gold badge28 silver badges46 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 5

You can use a partial path

cy.intercept({url: /^((?!.*\/_nuxt).+)$/}, (req) => {

or add the above negative lookahead to your existing regex

cy.intercept({url: /^(?!.*localhost:3001.*)(?!.*\/_nuxt).+$/})

As noted by @D.Nykl - it's better to intercept based on path rather than host & port, as these can change depending on where the page is served from.


Explanation

The bug is at this place in the Cypress code _doesRouteMatch.

When you provide a url it also attempts to match against the path portion of the URL the app uses.

Cypress source code abbreviated to show the relevant lines

export function _doesRouteMatch (routeMatcher: RouteMatcherOptions, req: CypressIncomingRequest) {

  const matchable = _getMatchableForRequest(req)
 
  ...

  // for convenience, attempt to match `url` against `path`?    
  const shouldTryMatchingPath = field === 'url'

  ...

  if (matcher.test) {
    if (!matcher.test(value) && 
       (!shouldTryMatchingPath || !matcher.test(matchable.path))) {
                               // ^ failing here
       return false
     }
     continue
   }

The matchable resolved from http://localhost:3001/_nuxt/components/Component.vue in the first line is:

Matchable object (partial) produced by _getMatchableForRequest(req)

matchable: {
  url: 'http://localhost:3001/_nuxt/components/Component.vue',
  path: '/_nuxt/components/Component.vue',
}

So it also tries this match on the path

/^((?!.*localhost:3001).+)$/.test('/_nuxt/components/Component.vue')

but of course that fails, and _doesRouteMatch does not return false as you would expect it to.

By including part of the path in the cy.intercept() regex you can avoid the bug.

If you want to suppress Cypress logs for a particular route, use

cy.intercept({ ... }, { log: false })     // separate intercept
  • from Disabling logs for a request
cy.intercept({url: '*'}, (req) => {
  if (!req.url.includes('_nuxt/')) {
    Cypress.log({ name: 'not "/_nuxt/"', message: req.url}) // for demo
  }
}).as('not-nuxt')

cy.intercept(/_nuxt/, {log:false}).as('nuxt')

cy.visit('https://hello-world.example.nuxt.space/')
cy.contains('div', 'Hello Nuxt 3!')

There seems to be a bug in the Cypress intercept code wrt negative lookahead, I could not get any variation to work.

You can however "consume" the localhost:3001 calls before your catch-all intercept.

The intercepts are processed in order of last-setup/first-matched, so if I try the following,

cy.intercept('*', (req) => {
  console.log(req.url)
})
cy.intercept(/jsonplaceholder/, req => req.continue())

cy.visit('/')              // baseUrl is "https://example.com"

cy.window().then(win => {
  win.fetch('https://jsonplaceholder.typicode.com/todos/1')
})

it does not log the call to jsonplaceholder

But if I comment out the second intercept

There may be a better way to handle this, but you could just intercept all calls, and handle the non-localhost calls differently than the localhost calls.

cy.intercept('**/*', (req) => {
  if (req.url.includes('localhost')) {
    req.continue();
  } else {
    // whatever needs to happen to non-localhost calls
  }
});

In the above, we're checking if the request URL contains localhost, and if it does, we send the request on - almost the same as if it were never intercepted to begin with.

本文标签: regex lookaroundscypress intercept to catch everything except baseUrl callsStack Overflow