8

RequestLogger

A have this test outside the main test controller, using page model and this recipe.

/**
  Used to get the periodic analytic id.
  Whenever we are viewing an asset, the server must respond with an id.
  This id is later used by the client, to send periodic analytics.

  @param {object} t          Testcafe's test controller
  @param {object} logger     A testcafe's RequestLogger.
  @returns {string}          Returns the periodic analytic id.
*/
async getPeriodicAnalyticId(t, logger) {
  const logPrefix = 'Get periodic analytic id > ';
  let responseBody;

  await t
    .expect(logger.requests.length).gt(0, logPrefix + 'No requests logged.');

  responseBody = logger.requests[0].response.body;

  await t
    .expect(responseBody).notTypeOf('undefined', logPrefix + 'Logged request does not have a response a body.')
    .expect(Buffer.isBuffer(responseBody)).eql(true, logPrefix + 'Invalid response body (not buffer)');

  // Periodic analytic id can be found on the server response of the 1st analytic sent.
  return JSON.parse(logger.requests[0].response.body.toString()).id;
}

Error

When running this test targeting a local Http server, works ok. But it fails when tests are targeting an https remote server. I get this error:

SyntaxError: Unexpected token  in JSON at position 0

on this line

return JSON.parse(logger.requests[0].response.body.toString()).id;

Debug info

Response Body from local Http server that works: localBuffer It translates to: localBufferToString

Response Body from remote https server that fails: remoteBuffer It translates to: remoteBufferToString

Question

I'm wondering if the method i use to convert the response body to json is ok. Currently i use:

JSON.parse(logger.requests[0].response.body.toString())

My environment

operating system: Windows 10
testcafe version: 0.21.1
node.js version: 9.3.0
Alex Skorkin
  • 4,264
  • 3
  • 25
  • 47
Aris Gatoudis
  • 103
  • 1
  • 8
  • I suggest you debug your test and check values of the logger.requests[0], logger.requests[0].response and logger.requests[0].response.body variables. It is possible that some of them return nothing. The following articles describe how to debug your test: https://devexpress.github.io/testcafe/documentation/recipes/debugging-with-visual-studio-code.html, https://devexpress.github.io/testcafe/documentation/recipes/debugging-with-chrome-dev-tools.html – Marion Aug 23 '18 at 07:55
  • Thank you Marion, i'll do that and report back. I forgot to say that the local server is on http and the remote on https, if that matters. (I updated the question) – Aris Gatoudis Aug 23 '18 at 08:17
  • I updated the debug info @Marion with screenshots from the debugger. – Aris Gatoudis Aug 23 '18 at 11:04
  • It is possible that the issue is related to TestCafe timeouts: t.expect waits for 3 seconds and this time might be not enough to load a resource. Try calling "wait" before "expect": await t.wait(4000).expect(logger.contains(record => record.response.statusCode === 200)).ok(); If this does not help, please update this example so that I can see the issue locally: https://github.com/MarinaRukavitsyna/TestCafe-RequestLogger-example/blob/master/index.js – Marion Aug 24 '18 at 09:00
  • @Marion This is not the case. On the main test controller there is a delay and an assertion for the statusCode of all requests collected, that passes.I will try to reproduce this on a simpler example on your code. – Aris Gatoudis Aug 27 '18 at 10:43
  • Hello @Marion. I created a similar test here https://github.com/prototype23/Testcafe-RequestLogger-example/blob/master/loggerResponse.js. It is not exactly what i'm doing on my real tests, but it reproduces my problem. As you can see the response from the logger is not readable. – Aris Gatoudis Aug 27 '18 at 15:06
  • I had this problem also because the response is the gzipped stream in my case. I had to implement an utility method to unzip the body stream before parsing JSON data. If it is your case also i can answer with the code i use for that. – Ricovitch Aug 30 '18 at 16:21
  • Hello @prototype23, your test passes properly on my side. The JSON.parse(logRecord.response.body) function works in Chrome on my side. Would you please specify your browser and OS settings? – Marion Sep 06 '18 at 11:48
  • @Ricovitch Hello. Thanks for the answer. I don't know if that's the case. It tried to implement this recipe https://nodejs.org/api/zlib.html#zlib_compressing_http_requests_and_responses but my response and response.body are not streams to pipe. Can you clone the example i created and test? You can find it one comment above. – Aris Gatoudis Sep 06 '18 at 21:38
  • Hi @Marion. My browser is the latest Firefox (Dev edition) on windows 10 @ work and on windows 7 @ home. But latest chrome fails too. – Aris Gatoudis Sep 06 '18 at 21:40
  • Hi @Marion maybe RequestLogger's option 'stringifyResponseBody': true should unzip any zipped response first, and then stringify. – Aris Gatoudis Oct 17 '18 at 18:09

1 Answers1

11

I had the same problem, because the server response was a gzipped response in my case, and testcafe logger API does not automatically unzip the response.

So we followed this steps :

Configure a logger with logResponseBody parameter (also as mentionned in comment, do not set 'stringifyResponseBody' parameter to true)

const logger = RequestLogger(
  /yourApiRegex/,
  { logResponseBody: true },
);

Write a helper method to unzip request body :

import zlib from 'zlib';

export const getBody = async body => new Promise((resolve, reject) => {
  zlib.gunzip(body, async (error, buff) => {
    if (error !== null) {
      return reject(error);
    }
    return resolve(JSON.parse(buff.toString()));
  });
});

Sample usage in tests

await t.expect(logger.contains(
  async (record) => {
    const body = await (getBody(record.response.body));
    return body.someProps === 'someValue';
  },
)).ok();
Ricovitch
  • 2,278
  • 1
  • 21
  • 28
  • Thank you! I will try to implemented this. A fast check on my example, where i get the body of the the 1st logged request only, didn't work. I'm getting: `Error: incorrect header check`. I will play around and report back or accept your answer tomorrow. – Aris Gatoudis Sep 07 '18 at 11:10
  • Hope you got it working. Please consider accepting my answer if it helped. – Ricovitch Sep 20 '18 at 15:35
  • Thank you for waiting @Ricovitch. Didn't find time to play around, yet. So i can't accept the answer yet. – Aris Gatoudis Sep 24 '18 at 10:29
  • 2
    Thank you @Ricovitch that was the reason i was getting gibberish. The response needed unzip. Maybe we should add 'stringifyResponseBody: false on your RequestLogger snippet. That's why i was getting errors while implementing your examples. I updated my example [here](https://github.com/prototype23/Testcafe-RequestLogger-example) too. – Aris Gatoudis Oct 17 '18 at 17:43
  • 1
    For anyone intrested, i created a second solution based on Ricovitch answer. An utility to unzip all the zipped responses from a logger. With this, you can keep your assertions clean . You can find the solution on the [same repo](https://github.com/prototype23/Testcafe-RequestLogger-example). I have placed 3 tags on the Git commits too. – Aris Gatoudis Oct 22 '18 at 13:09
  • I was getting same `Error: incorrect header check`. stringifyResponseBody to false fixed it for me as well. – nishantrevo Mar 12 '21 at 11:42