Skip to content

Cannot attach screenshot to cucumber report #275

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

Closed
vsuryawanshi opened this issue Nov 25, 2014 · 20 comments
Closed

Cannot attach screenshot to cucumber report #275

vsuryawanshi opened this issue Nov 25, 2014 · 20 comments

Comments

@vsuryawanshi
Copy link

No description provided.

@jlin412
Copy link

jlin412 commented Dec 17, 2014

Here is my code:

  this.After(function (scenario, done) {
    if (scenario.isFailed()) {
      browser.takeScreenshot().then(function (png) {
        scenario.attach(png, 'image/png');
      });
    }
  });

I know the screenshot data is good because I get write to an image file and it is displayed correctly like this:

  browser.takeScreenshot().then(function (png) {
        var fs = require('fs');
        var stream = fs.createWriteStream("test/e2e/output/screenshot.png");
        stream.write(new Buffer(png, 'base64'));
        stream.end();
      });

@simondean You work on screenshot feature.
Did I do something wrong? Or it is related to #249 and #255?

@jlin412
Copy link

jlin412 commented Dec 17, 2014

I am finally able to make it to work. This is my workaround:

      browser.takeScreenshot().then(function (png) {
        var fs = require('fs');

        //var base64Image = new Buffer(png, 'binary').toString('base64');
        var decodedImage = new Buffer(png, 'base64').toString('binary');

        scenario.attach(decodedImage, 'image/png');
      });

@nikulkarni
Copy link

@jlin412 that worked for me. thanks!

@jlin412
Copy link

jlin412 commented Dec 29, 2014

I think that we can close this issue because #249 and #255 are tracking this already.
Basically, scenario.attach will encode base64 so we can't pass it data/stream already encoded with base64. Scenario.attach should be able to handle this case. Most of modern screenshot method already return encoded data/stream.

@nikulkarni
Copy link

@jlin412 If understand current code, I see that scenario.attach doesn't encode to base64 anymore. I notice below attach() in scenario.js,
astTreeWalker.attach(data.toString(), mimeType);
and for streams it does,
astTreeWalker.attach(Buffer.concat(buffers).toString(), mimeType);

Previously ([email protected]) attach() method used to encode to base64 like below which is NOT the case anymore

astTreeWalker.attach(data.toString('base64'), mimeType);
and for streams it used to do,
astTreeWalker.attach(Buffer.concat(buffers).toString('base64'), mimeType);

@simondean
Copy link
Contributor

@nikulkarni the base64 encoding happens inside the JSON formatter. Cucumber's JSON formatter wrapps Gerkin's JSON formatter and it is Gerkin's JSON formatter that contains the base64 code. The code is in the encode64s function of https://github.com/cucumber/gherkin/blob/master/js/lib/gherkin/formatter/json_formatter.js

@nikulkarni
Copy link

oh I see, thanks for clearing that @simondean

@eoinyoneill
Copy link

@jlin412 I get the encoded data in testReport.json but they do not show up in the cucumber Report in Jenkins.

@jbpros jbpros added this to the major features milestone Jun 9, 2015
@cades
Copy link

cades commented Jun 18, 2015

@jlin412 ++
maybe we should place it in README or wiki?

@jbpros jbpros removed this from the major features milestone Oct 10, 2015
@karthiktv006
Copy link
Contributor

This works currently and examples are provided in README.md, i guess this bug can be closed.

@ambition-consulting
Copy link

The example on using WebDriver is not even syntactically correct, leave alone working. As stated above, the following works (using typescript and protractors browser instead of the general webdriver):

let hooks: cucumber.Hooks = this;
    hooks.After(function(scenario, callback) {
        if (scenario.isFailed()) {
            browser.manage().window().setSize(1024, 2048).then(result =>
              browser.takeScreenshot().then(function(stream) {
                  scenario.attach(new Buffer(stream, 'base64').toString('binary'), 'image/png', callback);
              }, function(err) {
                callback(err);
            }));
        }
        else {
          callback();
        }
    });

@charlierudolph
Copy link
Member

With 5fb6706 there is no intermediate conversion to string and we just encode it as base64 when adding it to the json output.

@nalbion
Copy link

nalbion commented Sep 6, 2016

@charlierudolph what if attachement.getData() is already base64 encoded? The output of browser.takeScreenshot() is...

This work-around is ugly, but it works: mrooding/gulp-protractor-cucumber-html-report#19

@charlierudolph
Copy link
Member

Hmm. okay. What do you think about the following rule: If a string is attached, doesn't base 64 encode it. If a stream / buffer is attached, the data will be base 64 encoded

@nalbion
Copy link

nalbion commented Sep 6, 2016

I notice that all of my base 64 encoded strings end with "=" and when encoded twice they end with "==". I'm not sure if that's a reliable indicator - it might be a valid final character of some images.

I suppose you're right though, images aren't strings, they are binary streams (or buffers)

@yogitasn
Copy link

yogitasn commented May 8, 2017

Hi All,

We use BDD Framework (Cucumber) automated with help of Protractor/Selenium and scripting language is Typescript. I am new to Cucumber/Typescript/Protractor. I am very keen on implementing the capture of screenshots for the failed steps in our framework. I have been researching on this topic from a long time now. Although i found solution to capture screenshots with the help of this thread however i am not able to make it work with Cucumber i.e. I have placed the capture screenshot code in the After hook but the After hook does not seem to be called.I have placed the After hook code in the file named Hooks.ts under support folder. Could anyone be able to let me know what am i missing here? Appreciate your help.

const Cucumber = require('cucumber');
var {defineSupportCode} = require('cucumber');
var fs = require('fs');
var Promise = require('bluebird');

defineSupportCode(function ({registerHandler, After}) {

After((scenario, done) => {
if (scenario.isFailed()) {
  return browser.takeScreenshot().then(function (result) {
    //scenario.attach(new Buffer(stream, 'base64').toString('binary'), 'image/png', callback);
    var stream = fs.createWriteStream(
      'C:\\Users\\Redirection\\XYZ\\Documents\\Screenshots\\exception.png');(Saving screenshots locally)
    stream.write(new Buffer(stream, 'base64'));
    stream.end();
    Promise.resolve(result);
  }, function (err) {
    //callback(err);
    Promise.reject(err);
  })
}

})
})

@nalbion
Copy link

nalbion commented May 9, 2017

@yogitasn you should not need bluebird if you're running on Node.

My features/steps/support/hooks.ts file looks like this:

import {browser} from 'protractor';
export = function () {
    this.Before(function (scenario, callback) {
        browser.manage().window().setSize(1270, 1200);
        browser.driver.get('about:blank').then(callback);
    });

    this.After(function (scenario, callback) {
        if (scenario.isFailed()) {
            browser.manage().window().setSize(1270, 1200).then(result =>
                browser.takeScreenshot().then(function (stream) {
                    let decodedImage = new Buffer(stream.replace(/^data:image\/(png|gif|jpeg);base64,/, ''), 'base64');
                    scenario.attach(decodedImage, 'image/png');
                    callback();
                }, function (err) {
                    callback(err);
                }));
        }
        else {
            callback();
        }
    });
};

@yogitasn
Copy link

yogitasn commented May 9, 2017

@nalbion Thank you so much. I will use your solution and check if its working for me.

@yogitasn
Copy link

yogitasn commented May 9, 2017

@nalbion,

I used the above solution with some minor changes as below however it did not seem to work :(. I added a import statement import { } from '../../support/hooks' in typescript files where the failed step function is called and also put console.log statement inside the After block and executed a failed test case. There was no output for the console statement on execution. Appreciate any suggestions.

"use strict";

//import {browser} from 'protractor';(This gave me error: Module ''protractor'' has no exported member 'browser'. Used below import statement)
import Element = protractor.Element;
var fs = require('fs');
export = function () {
/this.Before(function (scenario, callback) {
browser.manage().window().setSize(1270, 1200);
browser.driver.get('about:blank').then(callback);
});
/
this.After(function (scenario, callback) {
if (scenario.isFailed()) {
browser.manage().window().setSize(1270, 1200).then(result =>
browser.takeScreenshot().then(function (stream) {
console.log("Capturing screenshot")
let decodedImage = new Buffer(stream.replace(/^data:image/(png|gif|jpeg);base64,/, ''), 'base64');
scenario.attach(decodedImage, 'image/png');
callback();
}, function (err) {
callback(err);
}));
}
else {
callback();
}
});
};

I would also like to add that if i used the save screenshot code inside the After block i get different set of errors.
Error on using the local screenshot save code inside the After block

features2/support/Hooks.ts(83,22): error TS2403: Subsequent variable declarations must have the same type. Variable 'stream' must be of type 'string', but here has type 'any'.
features2/support/Hooks.ts(86,25): error TS2339: Property 'write' does not exist on type 'string'.
features2/support/Hooks.ts(87,25): error TS2339: Property 'end' does not exist on type 'string'.

this.After(function (scenario, callback) {
if (scenario.isFailed()) {
browser.manage().window().setSize(1270, 1200).then(result =>
browser.takeScreenshot().then(function (stream) {
console.log(scenario.isFailed())
//let decodedImage = new Buffer(stream.replace(/^data:image/(png|gif|jpeg);base64,/, ''), 'base64');
//scenario.attach(decodedImage, 'image/png');
var stream = fs.createWriteStream(
'C:\Users\Redirection\XYZ\Documents\Screenshots\exception.png');
console.log("Capturing Screenshot")
stream.write(new Buffer(stream, 'base64'));
stream.end();
callback();
}, function (err) {
callback(err);
}));
}
else {
callback();
}
});
};

Thanks

@lock
Copy link

lock bot commented Oct 25, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Oct 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests