cypress: `Cannot read property 'body' of null` error on cy.wait-ing for a request
Current behavior:
When waiting for a route/response, the first request is cancelled (unfortunately no idea why), and the second request (which contains the body, has status 200, etc.) is missed by the wait.
This leads to an error: Cannot read property 'body' of null
.
Please see the video here: https://dashboard.cypress.io/#/projects/5yp4q1/runs/443/failures/82eb323a-53a8-46a2-86e6-d9a64f4caa87
Here’s a screenshot with the error:
Here's the relevant piece of code
function performDocumentViewAction(windowId, documentViewAction, documentIdAliasName) {
cy.server();
const layoutAliasName = `visitWindow-layout-${new Date().getTime()}`;
cy.route('GET', new RegExp(`/rest/api/window/${windowId}/layout`)).as(layoutAliasName);
const dataAliasName = `visitWindow-data-${new Date().getTime()}`;
cy.route('GET', new RegExp(`/rest/api/window/${windowId}/[0-9]+$`)).as(dataAliasName);
documentViewAction();
cy.wait(`@${layoutAliasName}`, {
requestTimeout: 20000,
responseTimeout: 20000,
})
.wait(`@${dataAliasName}`, {
requestTimeout: 20000,
responseTimeout: 20000,
})
.then(xhr => {
return { documentId: xhr.response.body[0].id }; // here we get the null
})
.as(documentIdAliasName);
}
It can be read here: https://github.com/metasfresh/metasfresh-e2e/blob/master/cypress/support/commands/general.js#L251.
After much testing locally i have managed to repro this once, but locally i see no cancelled request, yet the null error still appears:
Here's the code i have used locally (the only difference is the logging and having to use cy.wrap)
function performDocumentViewAction(windowId, documentViewAction, documentIdAliasName) {
cy.server();
const layoutAliasName = `visitWindow-layout-${new Date().getTime()}`;
cy.route('GET', new RegExp(`/rest/api/window/${windowId}/layout`)).as(layoutAliasName);
const dataAliasName = `visitWindow-data-${new Date().getTime()}`;
cy.route('GET', new RegExp(`/rest/api/window/${windowId}/[0-9]+$`)).as(dataAliasName);
documentViewAction();
cy.wait(`@${layoutAliasName}`, {
requestTimeout: 20000,
responseTimeout: 20000,
})
.wait(`@${dataAliasName}`, {
requestTimeout: 20000,
responseTimeout: 20000,
})
.should(xhr => { // change here
cy.log('frist!: ' + JSON.stringify(xhr));
})
.then(xhr => {
cy.log('2nd: ' + JSON.stringify(xhr)); // change here
return cy.wrap({ documentId: xhr.response.body[0].id });
})
.as(documentIdAliasName);
}
Here’s the request as logged to console by cypress:
Here is the xhr from `cy.log`, and it can be seen that the path exists and contains a value (warning: HUGE)
let theXHR = {
xhr: {
method: 'GET',
url: 'https://dev630.metasfresh.com/rest/api/window/123/2156430',
id: 'xhr739',
},
id: 'xhr739',
url: 'https://dev630.metasfresh.com/rest/api/window/123/2156430',
method: 'GET',
status: 200,
statusMessage: '200 (OK)',
request: {
headers: {
Accept: 'application/json, text/plain, */*',
'Accept-Language': 'en_US',
},
body: null,
},
response: {
headers: {
date: 'Tue, 06 Aug 2019 06:48:03 GMT',
'content-encoding': 'gzip',
server: 'nginx/1.10.3 (Ubuntu)',
vary: 'Accept-Encoding',
'access-control-allow-methods': 'POST, GET, OPTIONS, DELETE, PATCH, PUT',
'content-type': 'application/json;charset=UTF-8',
'access-control-allow-origin': 'http://localhost:3000',
'access-control-max-age': '600',
'transfer-encoding': 'chunked',
connection: 'keep-alive',
'access-control-allow-credentials': 'true',
'access-control-allow-headers': 'x-requested-with, Content-Type, Origin, Accept-Language',
'x-application-context':
'metasfresh-webui-api:de.metas.vertical.healthcare.forum_datenaustausch_ch,metasfresh-webui-api:8443',
},
body: [
{
windowId: '123',
id: '2156430',
fieldsByName: {
ID: {
field: 'ID',
value: 2156430,
widgetType: 'Integer',
},
M_FreightCost_ID: {
field: 'M_FreightCost_ID',
value: null,
readonly: false,
mandatory: false,
displayed: true,
lookupValuesStale: true,
widgetType: 'List',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'M_FreightCost_ID',
},
viewEditorRenderMode: 'always',
},
M_Shipper_ID: {
field: 'M_Shipper_ID',
value: null,
readonly: false,
mandatory: false,
displayed: true,
lookupValuesStale: true,
widgetType: 'List',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'M_Shipper_ID',
},
viewEditorRenderMode: 'always',
},
AD_Client_ID: {
field: 'AD_Client_ID',
value: {
key: '1000000',
caption: 'metasfresh',
},
readonly: false,
mandatory: true,
displayed: true,
lookupValuesStale: true,
widgetType: 'List',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'AD_Client_ID',
},
viewEditorRenderMode: 'always',
},
AD_Org_ID: {
field: 'AD_Org_ID',
value: {
key: '1000000',
caption: 'metasfresh AG',
},
readonly: false,
mandatory: true,
displayed: true,
lookupValuesStale: true,
widgetType: 'List',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'AD_Org_ID',
},
viewEditorRenderMode: 'always',
},
Value: {
field: 'Value',
value: '1000004',
readonly: false,
mandatory: true,
displayed: true,
widgetType: 'Text',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'Value',
},
viewEditorRenderMode: 'always',
},
Name: {
field: 'Name',
value: 'vendor 1565074056375',
readonly: false,
mandatory: false,
displayed: false,
widgetType: 'Text',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'Name',
},
viewEditorRenderMode: 'always',
},
Name2: {
field: 'Name2',
value: 'vendor 1565074056375',
readonly: false,
mandatory: false,
displayed: true,
widgetType: 'Text',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'Name2',
},
viewEditorRenderMode: 'always',
},
Description: {
field: 'Description',
value: null,
readonly: false,
mandatory: false,
displayed: true,
widgetType: 'Text',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'Description',
},
viewEditorRenderMode: 'always',
},
IsActive: {
field: 'IsActive',
value: true,
readonly: false,
mandatory: true,
displayed: true,
widgetType: 'Switch',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'IsActive',
},
viewEditorRenderMode: 'always',
},
IsProducerAllotment: {
field: 'IsProducerAllotment',
value: false,
readonly: false,
mandatory: false,
displayed: true,
widgetType: 'YesNo',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'IsProducerAllotment',
},
viewEditorRenderMode: 'always',
},
IsCompany: {
field: 'IsCompany',
value: true,
readonly: false,
mandatory: false,
displayed: true,
widgetType: 'YesNo',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'IsCompany',
},
viewEditorRenderMode: 'always',
},
CompanyName: {
field: 'CompanyName',
value: 'vendor 1565074056375',
readonly: false,
mandatory: true,
displayed: true,
widgetType: 'Text',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'CompanyName',
},
viewEditorRenderMode: 'always',
},
VATaxID: {
field: 'VATaxID',
value: null,
readonly: false,
mandatory: false,
displayed: true,
widgetType: 'Text',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'VATaxID',
},
viewEditorRenderMode: 'always',
},
C_BP_Group_ID: {
field: 'C_BP_Group_ID',
value: {
key: '1000000',
caption: 'Standard',
},
readonly: false,
mandatory: true,
displayed: true,
lookupValuesStale: true,
widgetType: 'List',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'C_BP_Group_ID',
},
viewEditorRenderMode: 'always',
},
AD_Language: {
field: 'AD_Language',
value: {
key: 'en_US',
caption: 'English (US)',
},
readonly: false,
mandatory: false,
displayed: true,
lookupValuesStale: true,
widgetType: 'List',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'AD_Language',
},
viewEditorRenderMode: 'always',
},
IsEdiRecipient: {
field: 'IsEdiRecipient',
value: false,
readonly: false,
mandatory: true,
displayed: true,
widgetType: 'YesNo',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'IsEdiRecipient',
},
viewEditorRenderMode: 'always',
},
URL: {
field: 'URL',
value: null,
readonly: false,
mandatory: false,
displayed: true,
widgetType: 'Link',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'URL',
},
viewEditorRenderMode: 'always',
},
IsReplicationLookupDefault: {
field: 'IsReplicationLookupDefault',
value: false,
readonly: false,
mandatory: false,
displayed: true,
widgetType: 'YesNo',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'IsReplicationLookupDefault',
},
viewEditorRenderMode: 'always',
},
CreditLimitIndicator: {
field: 'CreditLimitIndicator',
value: null,
readonly: true,
mandatory: false,
displayed: true,
widgetType: 'Text',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'CreditLimitIndicator',
},
viewEditorRenderMode: 'never',
},
BPartner_Parent_ID: {
field: 'BPartner_Parent_ID',
value: null,
readonly: false,
mandatory: false,
displayed: true,
lookupValuesStale: true,
widgetType: 'Lookup',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'BPartner_Parent_ID',
},
viewEditorRenderMode: 'always',
},
Labels_548674: {
field: 'Labels_548674',
value: {
values: [],
},
readonly: false,
mandatory: false,
displayed: true,
lookupValuesStale: true,
widgetType: 'Labels',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'Labels_548674',
},
viewEditorRenderMode: 'always',
},
Labels_554470: {
field: 'Labels_554470',
value: {
values: [],
},
readonly: false,
mandatory: false,
displayed: true,
lookupValuesStale: true,
widgetType: 'Labels',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'Labels_554470',
},
viewEditorRenderMode: 'always',
},
V$DocumentSummary: {
field: 'V$DocumentSummary',
value: 'vendor 1565074056375 1000004',
readonly: true,
mandatory: false,
displayed: false,
widgetType: 'Text',
validStatus: {
valid: true,
initialValue: true,
fieldName: 'V$DocumentSummary',
},
viewEditorRenderMode: 'never',
},
},
validStatus: {
valid: true,
},
saveStatus: {
deleted: false,
saved: true,
hasChanges: false,
error: false,
reason: 'just loaded',
},
includedTabsInfo: {
'AD_Tab-541096': {
tabid: 'AD_Tab-541096',
allowCreateNew: true,
allowDelete: true,
},
'AD_Tab-540739': {
tabid: 'AD_Tab-540739',
allowCreateNew: false,
allowDelete: true,
},
'AD_Tab-540829': {
tabid: 'AD_Tab-540829',
allowCreateNew: false,
allowCreateNewReason: 'Tab is readonly',
allowDelete: false,
allowDeleteReason: 'Tab is readonly',
},
'AD_Tab-226': {
tabid: 'AD_Tab-226',
allowCreateNew: true,
allowDelete: true,
},
'AD_Tab-224': {
tabid: 'AD_Tab-224',
allowCreateNew: false,
allowDelete: true,
},
'AD_Tab-222': {
tabid: 'AD_Tab-222',
allowCreateNew: true,
allowDelete: true,
},
'AD_Tab-223': {
tabid: 'AD_Tab-223',
allowCreateNew: false,
allowDelete: true,
},
'AD_Tab-496': {
tabid: 'AD_Tab-496',
allowCreateNew: true,
allowDelete: true,
},
'AD_Tab-540737': {
tabid: 'AD_Tab-540737',
allowCreateNew: false,
allowCreateNewReason: 'Tab is readonly',
allowDelete: false,
allowDeleteReason: 'Tab is readonly',
},
'AD_Tab-541154': {
tabid: 'AD_Tab-541154',
allowCreateNew: false,
allowDelete: true,
},
'AD_Tab-541077': {
tabid: 'AD_Tab-541077',
allowCreateNew: true,
allowDelete: true,
},
'AD_Tab-541155': {
tabid: 'AD_Tab-541155',
allowCreateNew: true,
allowDelete: true,
},
'AD_Tab-540653': {
tabid: 'AD_Tab-540653',
allowCreateNew: true,
allowDelete: true,
},
'AD_Tab-540994': {
tabid: 'AD_Tab-540994',
allowCreateNew: true,
allowDelete: true,
},
},
standardActions: ['new', 'advancedEdit', 'email', 'letter', 'delete'],
websocketEndpoint: '/document/123/2156430',
},
],
},
duration: 395,
};
console.log(theXHR.response.body[0].id); // prints: "2156430"
Desired behavior:
Cypress should select the correct request and response.
Versions
Local machine: cypress 3.4.1, os: windows 10 x64, electron Jenkins machine: cypress 3.4.1, os: some linux x64 VPS, electron
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 8
- Comments: 23 (4 by maintainers)
Hello,
Is there an update about tracking this issue down, as it keeps happening (only when run in jenkins 🙄) and it keeps breaking our tests 😦 ?
Edit: Code was wrong at first but now should be fixed up
Hi @pmattj. So looking through the code. It is possible that
xhr
could be an array (though I don’t completely see how given the code that you sent). But just to rule it out. Could you do something like this?If we do that, you should be able to see true or false in the video on the dashboard
If it’s not an array, you could try doing this:
cy.log(JSON.stringify(xhr))
to try and output more information on what xhr actually is.