Installation
Simple as running ember install ember-cli-visual-acceptance
Testem.json
In order for ember-cli-visual-acceptance
to capture images, "launch_in_ci"
must contain ethier SlimerJsVisualAcceptance
or PhantomJsVisualAcceptance
.
Example:
{
"framework": "mocha",
"test_page": "tests/index.html?hidepassed",
"disable_watching": true,
"launch_in_ci": [
"SlimerJsVisualAcceptance"
],
"launch_in_dev": [
"Firefox"
],
"launchers": {
"PhantomJsVisualAcceptance": {
"command": "phantomjs vendor/phantomjs-launcher.js <url>",
"protocol": "browser"
},
"SlimerJsVisualAcceptance": {
"command": "slimerjs -jsconsole vendor/phantomjs-launcher.js <url>",
"protocol": "browser"
}
}
}
Usage
Inside an integration or acceptance test you can use return capture('<image-label>')
at the end of an it()
function.
it('renders', function () {
// Set any properties with this.set('myProperty', 'value')
// Handle any actions with this.on('myAction', function (val) { ... })
this.render(hbs`{{frost-file-picker}}`)
expect(this.$('.frost-file-picker')).to.have.length(1)
return capture('Basic-File-Picker')
})
You can also use this functionality for async testing:
it('renders', function (done) {
// Set any properties with this.set('myProperty', 'value')
// Handle any actions with this.on('myAction', function (val) { ... })
this.render(hbs`{{frost-file-picker}}`)
expect(this.$('.frost-file-picker')).to.have.length(1)
capture('Basic-File-Picker').then(function (data) {
console.log(arguments)
done()
}).catch(function (err) {
done(err)
})
})
In this case done comes from it('test', function (done) { … }
. You can also use the then
functionality to get creative rather than using done.
arguments
will display the response from ResembleJS or the message, 'No passed image. Saving current test as base'
(If there is no current baseline image).
Usage with Qunit
To use with Qunit you must supply the assert
parameter.
Example (Using ember-cli-showdown):
import hbs from 'htmlbars-inline-precompile';
import { moduleForComponent, test } from 'ember-qunit';
moduleForComponent('markdown-to-html', 'Integration | Component | markdown to html', {
integration: true
});
test('positional parameter', function(assert) {
assert.expect(1);
this.set('markdown', '*hello world*');
this.render(hbs`{{markdown-to-html markdown}}`);
assert.equal(this.$('> *').html(), '<p><em>hello world</em></p>');
return capture('Markdown', {assert: assert});
});
Larger frame
In order to go beyond the default 640x340px dimensions you can supply the width and height to the capture function. The following shows an example to get a 1920x4041 container: capture('<image-label>', {width: 1920, height: 4041}))
.
Targeting an element
ember-cli-visual-acceptance also has the ability to target a specific element. Given a DOM element ember-cli-visual-acceptance will capture the specified element rather than the default #ember-testing-container
. To target an element you must pass in the DOM element.
Target with an id
capture('Markdown', { targetElement: document.getElementById('foo')});
Target with class selectors
capture('drop-down-container', { targetElement: this.$('.drop-down-container')[0]})
Setting up travis
Replace ember test
with ember tva
. This command comes with ember-cli-visual-acceptance
and provides the functionality for commenting a report (Stored on Imgur) on a PR from the Travis build.
Add your github credentials to before_script:
before_script:
- git config --global user.email "ericwhite613@gmail.com"
- git config --global user.name "Eric White"
- git config --global push.default simple
- npm set progress=false
- git config credential.helper "store --file=.git/credentials"
- echo "https://${GH_TOKEN}:@github.com" > .git/credentials
Secure Variables (Display value in build log = OFF
)
-
Add
GH_TOKEN
to Travis. Personal Access Token must have push access
Unsecure Variables (Display value in build log = ON
)
-
Add
RO_GH_TOKEN
Unsecure token that can only read. -
Add
VISUAL_ACCEPTANCE_TOKEN
token, value can be found here -
If you put the
VISUAL_ACCEPTANCE_TOKEN
directly in your code and commit it to Github; Github will revoke the token. So it may be smart for you to create your own dummy Github account, and create a personal access token that has it’s repo scope set.
Pushing only when conditions are met
In some instances you may have multiple jobs with your Travis Builds. Wishing only to push in one. Ember-cli-visual-acceptance has added two options to ember tva
, push-var
and push-on
. Using these two options visual acceptance will only push when push-var
is equal to push-on
. For instance we could do ember tva --push-var=$EMBER_TRY_SCENARIO --push-on=default
, so visual acceptance will only push when doing the build job for EMBER_TRY_SCENARIO=default
.
Playing nice with Pr-bumper or doing your own push
Using push-var
and push-on
we can also stop visual-acceptance from pushing and having only pr-bumper or something else push. This can be accomplished with the following: ember tva --push-var='false'
Github Enterprise
The api endpoint can be specified with the --github-api-endpoint="http(s)://hostname/api/v3"
option
NightmareJS (Electron) vs Browsers - html2canvas vs. PhantomJS render callback
You must enable the display to use headless browsers by adding the following to the before_script
hook:
before_script:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
- sleep 3 # give xvfb some time to start
NightmareJS (Electron)
Nightmare takes a screenshot with Electron and provides the most accurate image. Using nightmare requires the nightmare
and nightmare-custom-event
packages to be saved to your dev dependencies npm install nightmare nightmare-custom-event --save-dev
(if using the visual acceptance blueprint this will be automatic)
If a captured image comes up blank or cutoff you should edit the vendor/nightmarejs-launcher.js
file to increase the viewport (the default is .viewport(3000, 10000)
width by height). The reason for this is Electron can only screenshot what it can see, and the test page continously grows with the more tests you have. This solution costs less than attempting to scroll the ember testing rectangle in frame, and resizing Electron to fit the image. Additionally, as long as Nightmare’s show
option is not set to true
you can get away with setting ludicrous sizes.
PhantomJS - SlimerJS
Personally I prefer using SlimerJS as their version of Gecko matches the latest Firefox. While PhantomJS Webkit is about a year behind Safari’s Webkit version. SlimerJsVisualAcceptance
images come out much more accurate. Additionally, debugging the images produced from the .ember-testing-container
in Firefox is useful. Since the .ember-testing-container
is identical in SlimerJS and Firefox ( at least I’ve never seen a difference between the two).
Warning
With certain repositories I’ve had trouble with SlimerJS having segmentation faults on both Linux and Mac. I’ve yet to resolve this issue.
Html2Canvas
Html2Canvas is used when a browser does not have the function window.callPhantom
(Only PhantomJS and SlimerJS have this defined). Html2Canvas is still in beta and as result you will see some issues.
Html2Canvas relies on Canvas drawing support. I find Chrome has the best Canvas drawing support (miles ahead of their competitors), while Firefox has the second best Canvas drawing support.
SVGs
Html2Canvas has difficulties rendering SVGs (more so in Firefox than in Chrome). As a result I have added a new expermental functionality that attempts to render the svgs better.
You can use this experimental feature by setting experimentalSvgs
to true
(Example: capture('svg-experimental',{ experimentalSvgs: true})
).
Experimental SVGs will not be used for PhantomJS, SlimerJS, and Chrome/Chromium (Chrome properly renders svgs with html2canvas) as their rendering handles SVGs (PhantomJS and SlimerJS basically just take a screenshot of the page)
Using Nightmare
{
"framework": "mocha",
"test_page": "tests/index.html?hidepassed",
"disable_watching": true,
"launch_in_ci": [
"NightmareJsVisualAcceptance"
],
"launch_in_dev": [
"Firefox"
],
"launchers": {
"PhantomJsVisualAcceptance": {
"command": "phantomjs vendor/phantomjs-launcher.js <url>",
"protocol": "browser"
},
"SlimerJsVisualAcceptance": {
"command": "slimerjs -jsconsole vendor/phantomjs-launcher.js <url>",
"protocol": "browser"
},
"NightmareJsVisualAcceptance": {
"command": "node vendor/nightmarejs-launcher.js <url>",
"protocol": "browser"
}
}
}
Using Chromium
To use Chromium on Travis set
"launch_in_ci": [
"Chromium"
],
If you’re using Mac OS X you’ll have to remove this when testing locally.
Using Firefox
To use Firefox on Travis simply set
"launch_in_ci": [
"Firefox"
],
And add the following to your .travis.yml
to get the latest version of Firefox:
addons:
firefox: "latest"
Using SlimerJS
{
"framework": "mocha",
"test_page": "tests/index.html?hidepassed",
"disable_watching": true,
"launch_in_ci": [
"SlimerJsVisualAcceptance"
],
"launch_in_dev": [
"Firefox"
],
"launchers": {
"PhantomJsVisualAcceptance": {
"command": "phantomjs vendor/phantomjs-launcher.js <url>",
"protocol": "browser"
},
"SlimerJsVisualAcceptance": {
"command": "slimerjs -jsconsole vendor/phantomjs-launcher.js <url>",
"protocol": "browser"
}
}
}
Using PhantomJS
{
"framework": "mocha",
"test_page": "tests/index.html?hidepassed",
"disable_watching": true,
"launch_in_ci": [
"PhantomJsVisualAcceptance"
],
"launch_in_dev": [
"Safari"
],
"launchers": {
"PhantomJsVisualAcceptance": {
"command": "phantomjs vendor/phantomjs-launcher.js <url>",
"protocol": "browser"
},
"SlimerJsVisualAcceptance": {
"command": "slimerjs -jsconsole vendor/phantomjs-launcher.js <url>",
"protocol": "browser"
}
}
}
Reports for multiple browsers
Producing a report for multiple browsers is perfectly fine. All you need to do is add your collection of browsers to launch_in_ci
.
Example:
"launch_in_ci": [
"Firefox",
"SlimerJsVisualAcceptance"
],
timeout of 2000ms exceeded
With Travis you may find you see this error a few times. Sometimes Travis can take a while to run capture (especially if you’re using experimentalSvgs and have a lot of svgs on the page), and exceeds the timeout.
To resolve this simply increase the timeout by doing this.timeout(5000)
in Mocha. I believe in Qunit you do QUnit.config.testTimeout = 5000
.
In Mocha you can also set the timeout globally in test-helper.js
:
import resolver from './helpers/resolver'
import { setResolver } from 'ember-mocha'
import { mocha } from 'mocha'
mocha.setup({
// customize as needed
timeout: 5000
})
setResolver(resolver)
In describeComponent
there is no this.timeout
. So you can set the timeout in the beforeEach fucntion by doing
describeComponent(
'frost-select',
'Integration: FrostSelectComponent',
{
integration: true
},
function () {
let props
let dropDown
beforeEach(function () {
this.test._timeout = 6000
})
...
})
Notes
-
Travis will upload the reports to Imgur
If you would like to help or have ideas on improving this tool I’m available on the Ember community slack @ewhite613 - issues and PRs also welcome :)