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

add matcher option to cy.route - addresses #387 #3984

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions packages/driver/src/cy/commands/xhr.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -358,11 +358,14 @@ module.exports = (Commands, Cypress, cy, state, config) ->

_.defaults(options, defaults)

if not options.url
$utils.throwErrByPath "route.url_missing"

if not (_.isString(options.url) or _.isRegExp(options.url))
$utils.throwErrByPath "route.url_invalid"
if options.matcher
if not _.isFunction(options.matcher)
$utils.throwErrByPath "route.matcher_invalid"
else
if not options.url
$utils.throwErrByPath "route.url_missing"
if not (_.isString(options.url) or _.isRegExp(options.url))
$utils.throwErrByPath "route.url_invalid"

if not $utils.isValidHttpMethod(options.method)
$utils.throwErrByPath "route.method_invalid", {
Expand Down
1 change: 1 addition & 0 deletions packages/driver/src/cypress/error_messages.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,7 @@ module.exports = {
route:
failed_prerequisites: "#{cmd('route')} cannot be invoked before starting the #{cmd('server')}"
invalid_arguments: "#{cmd('route')} was not provided any arguments. You must provide valid arguments."
matcher_invalid: "#{cmd('route')} was called with an invalid matcher option: matcher must be a Function that returns a Boolean."
method_invalid: "#{cmd('route')} was called with an invalid method: '{{method}}'. Method can be: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, or any other method supported by Node's HTTP parser."
response_invalid: "#{cmd('route')} cannot accept an undefined or null response. It must be set to something, even an empty string will work."
url_invalid: "#{cmd('route')} was called with an invalid url. Url must be either a string or regular expression."
Expand Down
1 change: 1 addition & 0 deletions packages/driver/src/cypress/server.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ create = (options = {}) ->
testStr(fullyQualifiedUrl, options.stripOrigin(fullyQualifiedUrl))

xhrMatchesRoute: (xhr, route) ->
return route.matcher(xhr, route) if _.isFunction(route.matcher)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add tests for the desired behavior?

The specs for cy.server, cy.route, etc. are all here: https://github.com/cypress-io/cypress/blob/develop/packages/driver/test/cypress/integration/commands/xhr_spec.coffee

server.methodsMatch(route.method, xhr.method) and server.urlsMatch(route.url, xhr.url)

add: (xhr, attrs = {}) ->
Expand Down
78 changes: 78 additions & 0 deletions packages/driver/test/cypress/integration/commands/xhr_spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -1332,6 +1332,76 @@ describe "src/cy/commands/xhr", ->
url: /foo/
respond: false

describe "matcher option", ->
it "accepts matcher option", ->
matcher = () => true
response = { foo: true }

cy.route({
matcher,
response,
}).then ->
@expectOptionsToBe({
matcher,
status: 200,
response
})

it "passes both xhr and options arguments to matcher option function", ->
cy
.window()
.then (win) ->
options = {
matcher: (xhr, _options) =>
expect(xhr instanceof win.XMLHttpRequest).to.be.true
expect(_options.matcher).to.eq(options.matcher)
expect(_options.response).to.eq(options.response)
response: 'foo',
}
cy
.route(options)
.window().then (win) ->
win.$.get("/foo")

it "receives request body in matcher", ->
options = {
matcher: (xhr) =>
expect(xhr.body).to.eq('baz')
}

cy
.route(options)
.window().then (win) ->
win.$.post("/foo", "baz")

it "ignores url when matcher option is present", ->
cy
.route({
url: "/bar"
matcher: (xhr, options) => /foo/.test(xhr.url)
response: 'foo',
}).as("getFoo")
.window().then (win) ->
win.$.get("/bar").catch((response) -> expect(response.status == 404))
.window().then (win) ->
win.$.get("/foo")
.wait("@getFoo").then (xhr) ->
expect(xhr.responseBody).to.eq 'foo'

it "ignores url when matcher option is present", ->
cy
.route({
url: "/bar"
matcher: (xhr, options) => /foo/.test(xhr.url)
response: 'foo',
}).as("getFoo")
.window().then (win) ->
win.$.get("/bar").catch((response) -> expect(response.status == 404))
.window().then (win) ->
win.$.get("/foo")
.wait("@getFoo").then (xhr) ->
expect(xhr.responseBody).to.eq 'foo'

describe "deprecations", ->
beforeEach ->
@warn = cy.spy(window.top.console, "warn")
Expand Down Expand Up @@ -1442,6 +1512,14 @@ describe "src/cy/commands/xhr", ->

cy.route(getUrl)

it "fails when matcher option is not a function", ->
cy.route({
matcher: 'foo',
})

cy.on "fail", (err) ->
expect(err.message).to.eq "cy.route() was called with an invalid matcher option: matcher must be a Function that returns a Boolean."

it "fails when functions reject", (done) ->
error = new Error

Expand Down