node.jsfrisby.jsinrule

frisby.js .post() - trouble sending xml in the body


I am attempting to test some APIs with frisby.js. I've run into trouble sending a block of xml via the .post() method. I can do it in Postman just fine.

Here is my code:

var xml_body = envSetup.ENV_DATA.inrule.xml_post_kia1;

frisby.create('InRule 02 Verify XML Post')
  .addHeaders({
    'Accept': 'application/xml',
    'Authorization': 'Basic <some internal token>',
    'Content-Length': xml_body.length,
    'Content-Type': 'application/xml'
  })
  .post(envSetup.URL + '/' + resource + '?action=basic', xml_body)
  .inspectRequest()

  .inspectBody()
  .expectStatus(200)
  .expectHeaderContains('Content-Type', 'application/xml')

.toss(); // InRule 02

Here is the output:

$ jasmine-node --color --verbose --config ENV inrule spec/inrule_spec.js
{ json: false,
  uri: 'http://dev.<company_api>/api/rules?action=basic',
  body: null,
  method: 'POST',
  headers:
   { accept: 'application/xml',
     authorization: 'Basic <some internal token>',
     'content-length': '787',
     'content-type': 'application/xml' },
  inspectOnFailure: false,
  baseUri: '',
  timeout: 5000 }
<RuleResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://<company_api>/resources/rules"><EntityData i:nil="true" /><Error>Unhandled Exception: Rules controller caught Exception: Object reference not set to an instance of an object.</Error><LogDetailLocation i:nil="true" /><ResponseText>Error Occurred</ResponseText><RuleApplication i:nil="true" /><Status>5</Status><StatusDescription i:nil="true" /></RuleResponse>

Frisby Test: InRule 01 Verify Get - 253 ms

        [ GET http://dev.<company_api>/api/rules?action=basic ] - 253 ms

Frisby Test: InRule 02 Verify Schema (Post) - 24 ms

        [ POST http://dev.<company_api>/api/rules?action=basic ] - 23 ms

Failures:

  1) Frisby Test: InRule 02 Verify Schema (Post)
        [ POST http://dev.<company_api>/api/rules?action=basic ]
   Message:
     Expected 500 to equal 200.
   Stacktrace:
     Error: Expected 500 to equal 200.
    at null.<anonymous> (H:\frisby\esb\node_modules\frisby\lib\frisby.js:493:42)
    at null.<anonymous> (H:\frisby\esb\node_modules\frisby\lib\frisby.js:1074:43)
    at Timer.listOnTimeout (timers.js:92:15)

Finished in 0.278 seconds
2 tests, 5 assertions, 1 failure, 0 skipped

I've tried with/without the 'Content-Length'

I've tried 'Content-Type': 'application/xml' and 'Content-Type': 'application/xml;charset=UTF-8'

I think the problem lies with the fact that the .inspectRequest() is showing

body: null,

When I look at the successful Postman 'Generate Code' for NodeJS Request it shows a body:

var options = { method: 'POST',
  url: 'http://dev.rules.itagroupservices.int/api/rules',
  qs: { action: 'basic' },
  headers: 
   { 'postman-token': '69bf39bc-3a6e-f1ea-7d8c-319ebbd41eef',
     'cache-control': 'no-cache',
     accept: 'application/xml',
     authorization: 'Basic <some internal token>',
     'content-type': 'application/xml' },
  body: '<RuleRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance"\r\n\t\txmlns="http://<company_api>/resources/rules">\r\n  \r\n  <EntityData>\r\n<![CDATA[bunch of xml data]]>\r\n    \r\n  </EntityData>\r\n</RuleRequest>' };

I don't know why frisby is not showing a body (and therefore not sending one?) even though I'm putting the xml_body where it should go.


Solution

  • Here is the official answer: In order to send XML you must send your request body as a piece of the header.

    frisby.create('Post XML to api')
      .post(someUrl, {}, {
        headers: headers4,
        body: xml1
        }
      )
      //.inspectRequest()
    
      //.inspectBody()
      .expectHeaderContains('Content-Type', 'application/xml')
      .expectStatus(200)
    .toss();
    

    You can see I've left the body portion empty with {} in the .post(url, body, header) format. Then in the third .post variable you give it a body: xmlVariable

    Another example here: https://github.com/vlucas/frisby/issues/290