BackstopJS icon indicating copy to clipboard operation
BackstopJS copied to clipboard

Will backstop JS work with Cypress tests?

Open mudra-octopus opened this issue 5 years ago • 3 comments

Hi Following up on https://github.com/garris/BackstopJS/issues/622#issuecomment-353752942 Is there any change to this situation? I would like to know if I can use Backstop JS with cypress tests.

mudra-octopus avatar Dec 15 '19 22:12 mudra-octopus

I don't know of any integrations with cypress -- I would ask on their issues page to see if someone has done it.

FWIW: Backstop was recently integrated into Ember -- there is a plugin for that here... https://github.com/garris/ember-backstop. It would be fairly straight-forward to implement a similar plugin for Cypress. I think cypress is cool and would happily provide some support for anyone who wanted to take this on.

garris avatar Dec 16 '19 16:12 garris

Here is how I solved it BackstopJS can be executed as a function so you can create a task.

Testing Patternlab using BackstopJS and Cypress

In plugins/index.js

const backstop = require('backstopjs');
// Place your initial backstop js config as a fixture
const config = require('../fixtures/backstop-base.json')


/**
 * Run BackstopJS as code 
 * Scenarios and Report folder name can be set via params
*/
function backstopExec(payload = {scenarios: [], folder:'default'}, refreshReferences = true) {
  return new Promise((resolve) => {
    const configuration = config
    config.scenarios = payload.scenarios
    config.paths.html_report = `cypress/reports/backstop/${payload.folder}/html_report`
    config.paths.ci_report = `cypress/reports/backstop/${payload.folder}/ci_report`

    if (refreshReferences) {
      backstop('reference', { config: configuration }).then(() => {
        resolve(null)
      }).catch(() => {
        resolve(null)
      })
    } else {
      backstop('test', { config: configuration }).then(() => {
        resolve(null)
      }).catch(() => {
        resolve(null)
      })
    }

  })
}

/**
 * @type {Cypress.PluginConfig}
 */
module.exports = (on, config) => {
  backstop('init')
   on('task', {
    log(message) {
      console.log(message)
      return null
    },
    backstopRefreshReferences(customConfig) {
      return backstopExec(customConfig)
    },
    backstopTest(customConfig) {
      return backstopExec(customConfig, false)
    }
  })
};

The configuration file that I'm importing, looks like this. cypress/fixtures/backstop-base.json

{
  "id": "schroff_homepage",
  "viewports": [
    {
      "label": "phone",
      "width": 375,
      "height": 812
    },
    {
      "label": "desktop",
      "width": 1200,
      "height": 800
    }
  ],
  "onBeforeScript": "puppet/onBefore.js",
  "onReadyScript": "puppet/onReady.js",
  "scenarios": [],
  "paths": {
    "bitmaps_reference": "cypress/reports/backstop_data/bitmaps_reference",
    "bitmaps_test": "cypress/reports/backstop_data/bitmaps_test",
    "engine_scripts": "cypress/reports/backstop_data/engine_scripts",
    "html_report": "cypress/reports/backstop/html_report",
    "ci_report": "cypress/reports/backstop/ci_report"
  },
  "report": ["browser"],
  "engine": "puppeteer",
  "engineOptions": {
    "args": ["--no-sandbox"]
  },
  "asyncCaptureLimit": 5,
  "asyncCompareLimit": 50,
  "debug": false,
  "debugWindow": false
}

Once you register the task you can use them within your tests. ( I use mochawesome to add links to the generated reports) if you run the task using cypress open then the reports are open automatically.

// Im getting my url from env
const baseUrl = Cypress.env('baseUrl')
// reset baseUrl by combining the two
Cypress.config("baseUrl", baseUrl)

// Reference URL for doing the compare
const refUrl = Cypress.env('refUrl') || false


let pages = [
  { label: 'base', url: `${baseUrl}/patterns/00-base/index.html`, hideSelectors },
  { label: 'atoms', url: `${baseUrl}/patterns/01-atoms/index.html`, hideSelectors },
  { label: 'patterns', url: `${baseUrl}/patterns/02-molecules/index.html`, hideSelectors },
  { label: 'organisms', url: `${baseUrl}/patterns/03-organisms/index.html`, hideSelectors },
  { label: 'templates', url: `${baseUrl}/patterns/04-templates/index.html`, hideSelectors },
  { label: 'pages', url: `${baseUrl}/patterns/05-pages/index.html`, hideSelectors },
]

describe('Using backstopjs', () => {
if (refUrl) {
    it('Generate report using Backstop JS', function () {
      // If ref URl is set, then it means we are in the right env for doing both refresh and test calls
      let refScenarios = []
      let testScenarios = []
      pages.forEach((scenario) => {
        const refScenarioUrl = scenario.url.replace(baseUrl, refUrl)
        const refScenario = { ...scenario }
        const testScenario = { ...scenario }
        refScenario.url = refScenarioUrl
        refScenarios.push(refScenario)
        testScenarios.push(testScenario)
      })
      cy.task('backstopRefreshReferences', { scenarios: refScenarios, folder: 'paternlab' }, { timeout: 820000 })
      cy.task('backstopTest', { scenarios: testScenarios, folder: 'patternlab' }, { timeout: 820000 })
      })
    })
  }
})

jscontreras avatar May 12 '20 13:05 jscontreras

@jscontreras how can I "tell" cypress to display a failed test, if the backstop test fails? (aka have differences)

In my case it works, but cypress is showing me "passed", instead of failed if differences in the screenshots are present.

cgpro avatar Dec 09 '22 11:12 cgpro