Open MaxNamazov opened 7 years ago
Any update about this? @jennifer-shehane?
Let me make sure I accurately understand your feature request.
You are able to set headers
within the cy.request()
options
object as documented here, but you would like 1 place to set the headers to affect all cy.request()
done, similar to how cy.server()
options affect routes
and requests
?
If this is the case, there is already a headers
key on cy.server()
that is solely used on stubbed cy.route()
, we'd have to resolve this conflict somehow or implement some other way.
:+1: for this. Would like to also have the option to globally set headers for all cy.visit() requests.
As a workaround I overwrite cy.request
method with my custom command:
Cypress.Commands.overwrite('request', (originalFn, ...options) => {
const optionsObject = options[0];
if (optionsObject === Object(optionsObject)) {
optionsObject.headers = {
authorization: 'Bearer YOUR_TOKEN',
...optionsObject.headers,
};
return originalFn(optionsObject);
}
return originalFn(...options);
});
Please note it only works if you use cy.request
with options
object.
I did my request like this, and it works very well(GET request):
it('myFunction()', function(){
cy.request(
{
url: 'https://url-you-want-to-request',
headers : {
'Service-Provider-Id' : 'name-etc',
'Client-Realm-Id': 'bla bla bla-',
'Application-Id': 'bla bla bla',
'Frontend-Id': 'XXX',
'Device-Id': 'device-id-number-etc',
'CID': 'co-relation-id-number-',
}
}
)
})
Similar to @Qwal's comment, I created a custom request()
command by overwriting the original, so I could set default options on the request (in this case basic auth headers).
This implementation supports the following usage patterns:
cy.request( options )
cy.request( url )
cy.request( method, url )
cy.request( method, url, body )
import _ from 'lodash';
// Overwrite cy.request() to set default options
Cypress.Commands.overwrite('request', (originalFn, ...args) => {
const defaults = {
auth: {
user: 'admin',
pass: 'password1'
}
};
let options = {};
if (_.isObject(args[0])) {
options = Object.assign({}, args[0]);
} else if (args.length === 1) {
[options.url] = args;
} else if (args.length === 2) {
[options.method, options.url] = args;
} else if (args.length === 3) {
[options.method, options.url, options.body] = args;
}
return originalFn(Object.assign({}, defaults, options));
});
I copied the logic from the base implementation of cy.request()
:
https://github.com/cypress-io/cypress/blob/develop/packages/driver/src/cy/commands/request.coffee#L61
Similar to this feature request, is there some way to set default headers for cy.visit
?
As I use the cucumber plugin, I did the following within a hooks.js file (next to your given.js, ... files)
import {ENV} from "../../../env";
const {
Before,
} = require("cypress-cucumber-preprocessor/steps");
const headers = {
'My-header-username': 'plop',
'My-header-Id': 1
};
//Before all
Before( () => {
Cypress.config('baseUrl', Cypress.env(`${ENV}BaseUrl`));
cy.wrap(headers).as('defaultHeaders'); // See usage below, in the step
});
Before({tags: '@oauth2'}, () => {
headers['My-Oauth2-Header'] = 'oauth2';
headers['My-Needed-Key'] = Cypress.env(`${ENV}Key`);
});
Before({tags: '@jwt'}, () => {
headers['My-Jwt-Header'] = 'jwt';
});
When(/^I do something$/, function () { // Don't use fat arrow here, as we use this. below
cy.request({
method: GET,
url: /myurl,
headers: this.defaultHeaders // Here is why I used cy.wrap() in the global before hook
}).then( (response) => {
cy.wrap(response).its('status').as('responseStatusCode');
cy.wrap(response).its('headers').as('responseHeaders');
cy.wrap(response).its('body').as('responseBody');
cy.wrap(response).its('duration').as('responseDuration');
})
});
Depending of the scenario tags, we'll either get the oauth2 or jwt headers. We'll always get the baseUrl one.
This is a dumb exemple of what can be done using global or tag-related befores. Hope this helps someone. This can work with cy.request(), cy.visit(), ... and does not need to redefine any of those. Which is great. But it does require cucumber.
We're using Cypress for some API testing and not having an easy way of setting a bearer token globally to the cy.request is a pain. I'll look at @Qwals approach as a stop gap but it feels like a missing feature to be able to specify this somewhere once rather than having to add the header to every cy.request.
I found a workaround for it:
cy.server({
onAnyRequest: function (route, proxy) {
proxy.xhr.setRequestHeader('CUSTOM-HEADER', 'Header value');
}
});
here's an updated version of https://github.com/cypress-io/cypress/issues/726#issuecomment-522378331 without lodash and deepmerging headers
// Overwrite cy.request() to set default options
Cypress.Commands.overwrite('request', (originalFn, ...args) => {
const defaults = {
headers: {
'Accept': 'application/json'
}
};
let options = {};
if (typeof args[0] === 'object' && args[0] !== null) {
options = args[0];
} else if (args.length === 1) {
[options.url] = args;
} else if (args.length === 2) {
[options.method, options.url] = args;
} else if (args.length === 3) {
[options.method, options.url, options.body] = args;
}
return originalFn({...defaults, ...options, ...{headers: {...defaults.headers, ...options.headers}}});
});
Based on @pitpit 's cy.request()
example, here is one for cy.visit()
Cypress.Commands.overwrite('visit', (originalFn, ...args) => {
const defaults = {
headers: {
'Accept': 'application/json'
}
};
let options = {};
if (typeof args[0] === 'object' && args[0] !== null) {
// cy.visit(options)
options = args[0];
} else if (args.length === 1) {
// cy.visit(url)
[options.url] = args;
} else if (args.length === 2) {
// cy.visit(url, options)
options = { ...args[1], url: args[0] };
}
return originalFn({...defaults, ...options, ...{headers: {...defaults.headers, ...options.headers}}});
});
Not tried yet, but according to the following, cy.intercept()
might help.
https://docs.cypress.io/api/commands/intercept#Request-Response-Modification-with-routeHandler
@jennifer-shehane Any update on this?
Not tried yet, but according to the following,
cy.intercept()
might help.https://docs.cypress.io/api/commands/intercept#Request-Response-Modification-with-routeHandler
https://docs.cypress.io/api/commands/request#cyintercept
cy.request does not go through intercept
Current behavior:
There is no possibility to add default headers for the
cy.request
command. The only way to add such headers is to overwrite this commandDesired behavior:
The possibility to set default headers (and maybe some other default options) for the
cy.request
command. For example, we useSessionId
header for authenticated requests in our app. And I would like to implement custom login command for my tests, so it would set this header as default for all subsequent requests.