garris / BackstopJS

Catch CSS curve balls.
http://backstopjs.org
MIT License
6.71k stars 602 forks source link

How to construct all scenarios based on user journey? #384

Open Mikuu opened 7 years ago

Mikuu commented 7 years ago

In one scenario I can write CasperJS to simulate the human interaction on the page and then BackstopJS can take the screenshot, but is it possible to construct all the scenarios according to a human user journey?

E.g.:

Current questions: Page B and C can't be directly accessed by visiting the URLs, I need login and some interaction in previous page, so to test scenario 3, is it a MUST to write all the previous steps (A->B->C) in its onReadyScript?

Not sure if i describe the question clearly.

garris commented 7 years ago

Hi @Mikuu. I think I understand your question. I think you should be able to do this -- but it is a little advanced. There are three ways to approach it. I will first explain what I recommend -- it is easier to implement and has way better performance but it may not work for your security config. Then I will explain the other slower way. There is a third option which I'll explain last...

approach 1 In most cases page B & C actually can be accessed directly -- but there is a cookie requirement that is fulfilled on a subsequent page. The absolute BEST to go here is to manually (in a real browser) log in on page A, then, go to page B. Once at page B (use a chrome extension to) export your cookies to a cookie file in your backstop folder. Then use an onBefore script to load the required cookie file before backstopjs actually requests your page. The script would look like this...

var fs = require('fs'),
    cookiePath = "backstop_data/cookies.json";

module.exports = function(casper, scenario, vp) {
  if (fs.exists(cookiePath)) {
    casper.page.cookies = JSON.parse(fs.read(cookiePath));
    console.log('Cookie state restored.');
  }

  casper.echo('setting user agent', 'INFO');
  casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36');

  casper.page.settings.webSecurityEnabled = false;
  casper.page.settings.localToRemoteUrlAccessEnabled = true;
};

You can repeat for page C. If this is something you are not familiar with I encourage you to discuss this with a backend developer who understands your system's auth process -- they may even be able to give you a cookie which will always be valid for your testing/dev environment.

approach 2 This is very straight forward but less performant and likely to break occasionally. The approach here is to just simulate what a user would do. When testing page B your scenario would define a URL for page A, but then use an onReady script to perform the interactions required to view page B.

It might look something like this.

var  cookiePath = "backstop_data/cookies.json";
var auth = {
       user: "xyz",
       pass: "xyz"
     };

module.exports = function(casper, scenario, vp) {
  casper.echo('Setting up test...', 'INFO');

  // LOG IN
  // ===================
  function doLogin() {
    casper.waitForSelector('input[name="Email"]', function() {
      this.sendKeys('input[name="Email"]', auth.user);
    });

    casper.then(function() {
      casper.mouseEvent('click', 'input#next');
    });

    casper.then(function() {
      casper.waitForSelector('input#Passwd', function() {
        this.sendKeys('input#Passwd', auth.pass);
        this.mouseEvent('click', 'input#signIn'); //This should take you to page B
      });
    });
  }

  doLogin();

  //this block is optional. see approach 3 below for info on why this is here...
  casper.then(function() {
    console.log("Saving cookies.")
    var cookies = JSON.stringify(casper.page.cookies, null, 2);
    fs.write(cookiePath, cookies, 'w');
  });

This will take some time to create. It will run relatively slowly, and troubleshooting will require trial and error. So, I don't really recommend it -- that said, sometimes this is the best/only way.

A slightly different approach would be to combine the above examples.

approach 3 You could create a separate backstop config file which uses the approach 2 to occasionally generate and cache your cookie file. Then in your regular backstop.json file use approach 1 for all of your testing. Simply run approach 2 if a cookie or URL goes stale.

Hope this helps! Please let me know how you end up addressing the issue. I want to write a blog article for this so your feedback will help a lot.

Cheers!