diff --git a/.gitignore b/.gitignore index d0963d86caed2..4f697649a07d8 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ target /test/screenshots/diff /test/screenshots/failure /test/screenshots/session +/test/screenshots/visual_regression_gallery.html /esvm .htpasswd .eslintcache diff --git a/package.json b/package.json index 42b3f7b9d7330..f1b6f338368a6 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "Tim Sullivan " ], "scripts": { - "test": "grunt test", + "test": "grunt test; grunt test:visualRegression", "test:dev": "grunt test:dev", "test:quick": "grunt test:quick", "test:browser": "grunt test:browser", @@ -59,8 +59,7 @@ "makelogs": "makelogs", "mocha": "mocha", "mocha:debug": "mocha --debug-brk", - "sterilize": "grunt sterilize", - "compareScreenshots": "node utilities/compareScreenshots" + "sterilize": "grunt sterilize" }, "repository": { "type": "git", @@ -153,6 +152,7 @@ "auto-release-sinon": "1.0.3", "babel-eslint": "4.1.8", "chokidar": "1.4.3", + "dot": "1.0.3", "elasticdump": "2.1.1", "eslint": "1.10.3", "eslint-plugin-mocha": "1.1.0", @@ -191,7 +191,7 @@ "nock": "2.10.0", "npm": "2.11.0", "portscanner": "1.0.0", - "simple-git": "1.8.0", + "simple-git": "1.37.0", "sinon": "1.17.2", "source-map": "0.4.4", "source-map-support": "0.4.0", diff --git a/tasks/config/clean.js b/tasks/config/clean.js index f83a816085567..4128505fd189e 100644 --- a/tasks/config/clean.js +++ b/tasks/config/clean.js @@ -3,6 +3,7 @@ module.exports = function (grunt) { return { build: 'build', target: 'target', + screenshots: 'test/screenshots/session', testsFromModules: 'build/kibana/node_modules/**/{test,tests}/**', deepModuleBins: 'build/kibana/node_modules/*/node_modules/**/.bin/{' + modules.join(',') + '}', deepModules: 'build/kibana/node_modules/*/node_modules/**/{' + modules.join(',') + '}/', diff --git a/tasks/test.js b/tasks/test.js index 7fab931c0d508..177e794aaa3f4 100644 --- a/tasks/test.js +++ b/tasks/test.js @@ -1,5 +1,16 @@ -var _ = require('lodash'); +const _ = require('lodash'); +const visualRegression = require('../utilities/visual_regression'); + module.exports = function (grunt) { + grunt.registerTask( + 'test:visualRegression', + 'Compare screenshots and generate diff images.', + function () { + const done = this.async(); + visualRegression.run(done); + } + ); + grunt.registerTask('test:server', [ 'esvm:test', 'simplemocha:all', 'esvm_shutdown:test' ]); grunt.registerTask('test:browser', [ 'run:testServer', 'karma:unit' ]); grunt.registerTask('test:coverage', [ 'run:testCoverageServer', 'karma:coverage' ]); @@ -21,6 +32,7 @@ module.exports = function (grunt) { 'run:testUIServer', 'downloadSelenium', 'run:seleniumServer', + 'clean:screenshots', 'intern:dev', 'esvm_shutdown:ui', 'stop:seleniumServer', @@ -35,6 +47,7 @@ module.exports = function (grunt) { ]); grunt.registerTask('test:ui:runner', [ + 'clean:screenshots', 'intern:dev' ]); @@ -55,7 +68,7 @@ module.exports = function (grunt) { 'intern:api' ]); - grunt.registerTask('test', function (subTask) { + grunt.registerTask('test', subTask => { if (subTask) grunt.fail.fatal(`invalid task "test:${subTask}"`); grunt.task.run(_.compact([ diff --git a/test/functional/apps/console/_console.js b/test/functional/apps/console/_console.js index 2f96481dca0d1..92b505e4390c6 100644 --- a/test/functional/apps/console/_console.js +++ b/test/functional/apps/console/_console.js @@ -13,7 +13,6 @@ bdd.describe('console app', function describeIndexTests() { return common.navigateToApp('console', false); }); - bdd.it('should show the default request', function () { var expectedRequest = [ 'GET _search', @@ -24,9 +23,11 @@ bdd.describe('console app', function describeIndexTests() { '}', '' ]; + common.saveScreenshot('Console-help-expanded'); // collapse the help pane because we only get the VISIBLE TEXT, not the part that is scrolled return consolePage.collapseHelp() .then(function () { + common.saveScreenshot('Console-help-collapsed'); return common.try(function () { return consolePage.getRequest() .then(function (actualRequest) { @@ -40,6 +41,7 @@ bdd.describe('console app', function describeIndexTests() { var expectedResponseContains = '"_index": ".kibana",'; return consolePage.clickPlay() .then(function () { + common.saveScreenshot('Console-default-request'); return common.try(function () { return consolePage.getResponse() .then(function (actualResponse) { diff --git a/test/functional/apps/dashboard/_dashboard.js b/test/functional/apps/dashboard/_dashboard.js index 7c045ac614a26..a69e47d4af086 100644 --- a/test/functional/apps/dashboard/_dashboard.js +++ b/test/functional/apps/dashboard/_dashboard.js @@ -42,6 +42,8 @@ bdd.describe('dashboard tab', function describeIndexTests() { ]; bdd.it('should be able to add visualizations to dashboard', function addVisualizations() { + common.saveScreenshot('Dashboard-no-visualizations'); + function addVisualizations(arr) { return arr.reduce(function (promise, vizName) { return promise @@ -54,13 +56,13 @@ bdd.describe('dashboard tab', function describeIndexTests() { return addVisualizations(visualizations) .then(function () { common.debug('done adding visualizations'); + common.saveScreenshot('Dashboard-add-visualizations'); }); }); bdd.it('set the timepicker time to that which contains our test data', function setTimepicker() { var fromTime = '2015-09-19 06:31:44.000'; var toTime = '2015-09-23 18:31:44.000'; - var testSubName = 'Dashboard Test 1'; // .then(function () { common.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"'); @@ -69,21 +71,23 @@ bdd.describe('dashboard tab', function describeIndexTests() { return common.sleep(4000); }) .then(function takeScreenshot() { - common.debug('Take screenshot'); - common.saveScreenshot('./screenshot-' + testSubName + '.png'); + common.saveScreenshot('Dashboard-set-timepicker'); }); }); bdd.it('should save and load dashboard', function saveAndLoadDashboard() { - var testSubName = 'Dashboard Test 1'; + const dashboardName = 'Dashboard Test 1'; // TODO: save time on the dashboard and test it - return dashboardPage.saveDashboard(testSubName) + return dashboardPage.saveDashboard(dashboardName) // click New Dashboard just to clear the one we just created .then(function () { return dashboardPage.clickNewDashboard(); }) .then(function () { - return dashboardPage.loadSavedDashboard(testSubName); + return dashboardPage.loadSavedDashboard(dashboardName); + }) + .then(function () { + common.saveScreenshot('Dashboard-load-saved'); }); }); @@ -94,6 +98,9 @@ bdd.describe('dashboard tab', function describeIndexTests() { common.log('visualization titles = ' + panelTitles); expect(panelTitles).to.eql(visualizations); }); + }) + .then(function () { + common.saveScreenshot('Dashboard-has-visualizations'); }); }); @@ -110,6 +117,7 @@ bdd.describe('dashboard tab', function describeIndexTests() { return dashboardPage.getPanelData() .then(function (panelTitles) { common.log('visualization titles = ' + panelTitles); + common.saveScreenshot('Dashboard-visualization-sizes'); expect(panelTitles).to.eql(visObjects); }); }); diff --git a/test/functional/apps/discover/_collapse_expand.js b/test/functional/apps/discover/_collapse_expand.js index 354638990d286..52b2e40f269c1 100644 --- a/test/functional/apps/discover/_collapse_expand.js +++ b/test/functional/apps/discover/_collapse_expand.js @@ -38,6 +38,7 @@ bdd.describe('discover tab', function describeIndexTests() { bdd.describe('field data', function () { bdd.it('should initially be expanded', function () { + common.saveScreenshot('Discover-sidebar-expanded'); return discoverPage.getSidebarWidth() .then(function (width) { common.debug('expanded sidebar width = ' + width); @@ -48,6 +49,7 @@ bdd.describe('discover tab', function describeIndexTests() { bdd.it('should collapse when clicked', function () { return discoverPage.toggleSidebarCollapse() .then(function () { + common.saveScreenshot('Discover-sidebar-collapsed'); common.debug('discoverPage.getSidebarWidth()'); return discoverPage.getSidebarWidth(); }) diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js index abb8f8e5bd9cb..d2a51b3a66418 100644 --- a/test/functional/apps/discover/_discover.js +++ b/test/functional/apps/discover/_discover.js @@ -58,6 +58,7 @@ bdd.describe('discover app', function describeIndexTests() { return headerPage.getToastMessage(); }) .then(function (toastMessage) { + common.saveScreenshot('Discover-save-query-toast'); expect(toastMessage).to.be(expectedSavedQueryMessage); }) .then(function () { @@ -80,6 +81,7 @@ bdd.describe('discover app', function describeIndexTests() { return discoverPage.getCurrentQueryName(); }) .then(function (actualQueryNameString) { + common.saveScreenshot('Discover-load-query'); expect(actualQueryNameString).to.be(queryName1); }); }); @@ -289,6 +291,7 @@ bdd.describe('discover app', function describeIndexTests() { bdd.it('should show "no results"', () => { return discoverPage.hasNoResults().then(visible => { + common.saveScreenshot('Discover-no-results'); expect(visible).to.be(true); }); }); diff --git a/test/functional/apps/discover/_field_data.js b/test/functional/apps/discover/_field_data.js index eac33162b91bf..7d94ef978e8a7 100644 --- a/test/functional/apps/discover/_field_data.js +++ b/test/functional/apps/discover/_field_data.js @@ -49,6 +49,7 @@ bdd.describe('discover app', function describeIndexTests() { return common.try(function tryingForTime() { return discoverPage.getHitCount() .then(function compareData(hitCount) { + common.saveScreenshot('Discover-field-data'); expect(hitCount).to.be(expectedHitCount); }); }); @@ -64,7 +65,6 @@ bdd.describe('discover app', function describeIndexTests() { }); }); - bdd.it('search _type:apache should show the correct hit count', function () { var expectedHitCount = '11,156'; return discoverPage.query('_type:apache') @@ -222,6 +222,7 @@ bdd.describe('discover app', function describeIndexTests() { return common.try(function tryingForTime() { return discoverPage.getDocTableIndex(1) .then(function (rowData) { + common.saveScreenshot('Discover-sort-down'); expect(rowData).to.be(ExpectedDoc); }); }); @@ -237,6 +238,7 @@ bdd.describe('discover app', function describeIndexTests() { return headerPage.getToastMessage(); }) .then(function (toastMessage) { + common.saveScreenshot('Discover-syntax-error-toast'); expect(toastMessage).to.be(expectedError); }) .then(function () { diff --git a/test/functional/apps/discover/_shared_links.js b/test/functional/apps/discover/_shared_links.js index dbbe940b115fc..2b4e205c484f6 100644 --- a/test/functional/apps/discover/_shared_links.js +++ b/test/functional/apps/discover/_shared_links.js @@ -56,6 +56,7 @@ bdd.describe('shared links', function describeIndexTests() { var expectedCaption = 'Share a link'; return discoverPage.clickShare() .then(function () { + common.saveScreenshot('Discover-share-link'); return discoverPage.getShareCaption(); }) .then(function (actualCaption) { @@ -85,6 +86,7 @@ bdd.describe('shared links', function describeIndexTests() { return headerPage.getToastMessage(); }) .then(function (toastMessage) { + common.saveScreenshot('Discover-copy-to-clipboard-toast'); expect(toastMessage).to.match(expectedToastMessage); }) .then(function () { @@ -98,6 +100,7 @@ bdd.describe('shared links', function describeIndexTests() { return discoverPage.clickShortenUrl() .then(function () { return common.try(function tryingForTime() { + common.saveScreenshot('Discover-shorten-url-button'); return discoverPage.getShortenedUrl() .then(function (actualUrl) { expect(actualUrl).to.match(re); diff --git a/test/functional/apps/settings/_advanced_settings.js b/test/functional/apps/settings/_advanced_settings.js index b85b4b4ee0493..498842801fbd2 100644 --- a/test/functional/apps/settings/_advanced_settings.js +++ b/test/functional/apps/settings/_advanced_settings.js @@ -25,10 +25,12 @@ bdd.describe('creating and deleting default index', function describeIndexTests( bdd.it('should allow setting advanced settings', function () { return settingsPage.clickAdvancedTab() .then(function TestCallSetAdvancedSettingsForTimezone() { + common.saveScreenshot('Settings-advanced-tab'); common.debug('calling setAdvancedSetting'); return settingsPage.setAdvancedSettings('dateFormat:tz', 'America/Phoenix'); }) .then(function GetAdvancedSetting() { + common.saveScreenshot('Settings-set-timezone'); return settingsPage.getAdvancedSettings('dateFormat:tz'); }) .then(function (advancedSetting) { diff --git a/test/functional/apps/settings/_creation_form_changes.js b/test/functional/apps/settings/_creation_form_changes.js index f80d771a127ba..fb3b8bf497fea 100644 --- a/test/functional/apps/settings/_creation_form_changes.js +++ b/test/functional/apps/settings/_creation_form_changes.js @@ -30,6 +30,7 @@ bdd.describe('user input reactions', function () { return settingsPage.getTimeBasedIndexPatternCheckbox(waitTime); }) .then(function () { + common.saveScreenshot('Settings-indices-hide-time-based-index-pattern'); // we expect the promise above to fail var handler = common.handleError(self); var msg = 'Found time based index pattern checkbox'; @@ -47,6 +48,7 @@ bdd.describe('user input reactions', function () { .then(function () { return settingsPage.getCreateButton().isEnabled() .then(function (enabled) { + common.saveScreenshot('Settings-indices-enable-creation'); expect(enabled).to.be.ok(); }); }); diff --git a/test/functional/apps/settings/_index_pattern_create_delete.js b/test/functional/apps/settings/_index_pattern_create_delete.js index 0578662e76ea5..1ad16594f7b3f 100644 --- a/test/functional/apps/settings/_index_pattern_create_delete.js +++ b/test/functional/apps/settings/_index_pattern_create_delete.js @@ -26,6 +26,7 @@ bdd.describe('creating and deleting default index', function describeIndexTests( bdd.it('should have index pattern in page header', function pageHeader() { return settingsPage.getIndexPageHeading().getVisibleText() .then(function (patternName) { + common.saveScreenshot('Settings-indices-new-index-pattern'); expect(patternName).to.be('logstash-*'); }); }); @@ -72,6 +73,7 @@ bdd.describe('creating and deleting default index', function describeIndexTests( var expectedAlertText = 'Are you sure you want to remove this index pattern?'; return settingsPage.removeIndexPattern() .then(function (alertText) { + common.saveScreenshot('Settings-indices-confirm-remove-index-pattern'); expect(alertText).to.be(expectedAlertText); }); }); diff --git a/test/functional/apps/settings/_index_pattern_popularity.js b/test/functional/apps/settings/_index_pattern_popularity.js index f7bb041db67f3..97f9d84a6b488 100644 --- a/test/functional/apps/settings/_index_pattern_popularity.js +++ b/test/functional/apps/settings/_index_pattern_popularity.js @@ -63,6 +63,7 @@ bdd.describe('index result popularity', function describeIndexTests() { .then(function (popularity) { common.debug('popularity = ' + popularity); expect(popularity).to.be('1'); + common.saveScreenshot('Settings-indices-result-popularity-updated'); }); }); @@ -101,6 +102,7 @@ bdd.describe('index result popularity', function describeIndexTests() { .then(function (popularity) { common.debug('popularity = ' + popularity); expect(popularity).to.be('1'); + common.saveScreenshot('Settings-indices-result-popularity-saved'); }); }); }); // end 'change popularity' diff --git a/test/functional/apps/settings/_index_pattern_results_sort.js b/test/functional/apps/settings/_index_pattern_results_sort.js index 5f2fc88a52ac7..50e1ade1ac2ef 100644 --- a/test/functional/apps/settings/_index_pattern_results_sort.js +++ b/test/functional/apps/settings/_index_pattern_results_sort.js @@ -51,6 +51,7 @@ bdd.describe('index result field sort', function describeIndexTests() { return col.selector(); }) .then(function (rowText) { + common.saveScreenshot(`Settings-indices-column-${col.heading}-sort-ascending`); expect(rowText).to.be(col.first); }); }); @@ -64,6 +65,7 @@ bdd.describe('index result field sort', function describeIndexTests() { return col.selector(); }) .then(function (rowText) { + common.saveScreenshot(`Settings-indices-column-${col.heading}-sort-descending`); expect(rowText).to.be(col.last); }); }); @@ -115,6 +117,7 @@ bdd.describe('index result field sort', function describeIndexTests() { return settingsPage.getPageFieldCount(); }) .then(function (pageCount) { + common.saveScreenshot('Settings-indices-paged'); var expectedSize = (val < 4) ? expectedDefaultPageSize : expectedLastPageCount; expect(pageCount.length).to.be(expectedSize); }); diff --git a/test/functional/apps/settings/_initial_state.js b/test/functional/apps/settings/_initial_state.js index 8d844572dd55e..c5cdc243cba3d 100644 --- a/test/functional/apps/settings/_initial_state.js +++ b/test/functional/apps/settings/_initial_state.js @@ -20,6 +20,7 @@ bdd.describe('initial state', function () { bdd.it('should load with time pattern checked', function () { return settingsPage.getTimeBasedEventsCheckbox().isSelected() .then(function (selected) { + common.saveScreenshot('Settings-initial-state'); expect(selected).to.be.ok(); }); }); diff --git a/test/functional/apps/visualize/_area_chart.js b/test/functional/apps/visualize/_area_chart.js index b95c5275b85b6..de0eab0c140b4 100644 --- a/test/functional/apps/visualize/_area_chart.js +++ b/test/functional/apps/visualize/_area_chart.js @@ -61,13 +61,13 @@ bdd.describe('visualize app', function describeIndexTests() { }); bdd.describe('area charts', function indexPatternCreation() { - var testSubName = 'AreaChart'; - var vizName1 = 'Visualization ' + testSubName; + var vizName1 = 'Visualization AreaChart'; bdd.it('should save and load', function pageHeader() { return visualizePage.saveVisualization(vizName1) .then(function (message) { common.debug('Saved viz message = ' + message); + common.saveScreenshot('Visualize-area-chart-save-toast'); expect(message).to.be('Visualization Editor: Saved Visualization \"' + vizName1 + '\"'); }) .then(function testVisualizeWaitForToastMessageGone() { @@ -87,7 +87,6 @@ bdd.describe('visualize app', function describeIndexTests() { }); }); - bdd.it('should show correct chart, take screenshot', function pageHeader() { var chartHeight = 0; var xAxisLabels = [ '2015-09-20 00:00', '2015-09-21 00:00', @@ -118,15 +117,11 @@ bdd.describe('visualize app', function describeIndexTests() { .then(function (paths) { common.debug('expectedAreaChartData = ' + expectedAreaChartData); common.debug('actual chart data = ' + paths); + common.saveScreenshot('Visualize-area-chart'); expect(paths).to.eql(expectedAreaChartData); - }) - .then(function takeScreenshot() { - common.debug('Take screenshot'); - common.saveScreenshot('./screenshot-' + testSubName + '.png'); }); }); - bdd.it('should show correct data', function pageHeader() { var expectedTableData = [ 'September 20th 2015, 00:00:00.000 37', 'September 20th 2015, 03:00:00.000 202', @@ -166,8 +161,5 @@ bdd.describe('visualize app', function describeIndexTests() { expect(data.trim().split('\n')).to.eql(expectedTableData); }); }); - - - }); }); diff --git a/test/functional/apps/visualize/_chart_types.js b/test/functional/apps/visualize/_chart_types.js index 1e375de7f868a..6d9cc2e9b3cb3 100644 --- a/test/functional/apps/visualize/_chart_types.js +++ b/test/functional/apps/visualize/_chart_types.js @@ -16,9 +16,7 @@ bdd.describe('visualize app', function describeIndexTests() { }); bdd.describe('chart types', function indexPatternCreation() { - bdd.it('should show the correct chart types', function pageHeader() { - var expectedChartTypes = [ 'Area chart', 'Data table', 'Line chart', 'Markdown widget', 'Metric', 'Pie chart', 'Tile map', 'Vertical bar chart' @@ -28,6 +26,7 @@ bdd.describe('visualize app', function describeIndexTests() { .then(function testChartTypes(chartTypes) { common.debug('returned chart types = ' + chartTypes); common.debug('expected chart types = ' + expectedChartTypes); + common.saveScreenshot('Visualize-chart-types'); expect(chartTypes).to.eql(expectedChartTypes); }); }); diff --git a/test/functional/apps/visualize/_data_table.js b/test/functional/apps/visualize/_data_table.js index 8734f51a54ac3..302825c8cf51f 100644 --- a/test/functional/apps/visualize/_data_table.js +++ b/test/functional/apps/visualize/_data_table.js @@ -52,10 +52,8 @@ bdd.describe('visualize app', function describeIndexTests() { }); }); - bdd.describe('data table', function indexPatternCreation() { - var testSubName = 'DataTable'; - var vizName1 = 'Visualization ' + testSubName; + var vizName1 = 'Visualization DataTable'; bdd.it('should be able to save and load', function pageHeader() { return visualizePage.saveVisualization(vizName1) @@ -74,7 +72,6 @@ bdd.describe('visualize app', function describeIndexTests() { }); }); - bdd.it('should show correct data, take screenshot', function pageHeader() { var chartHeight = 0; var expectedChartData = [ '0 2,088', '2,000 2,748', '4,000 2,707', '6,000 2,876', @@ -84,14 +81,10 @@ bdd.describe('visualize app', function describeIndexTests() { return visualizePage.getDataTableData() .then(function showData(data) { common.debug(data.split('\n')); + common.saveScreenshot('Visualize-data-table'); expect(data.split('\n')).to.eql(expectedChartData); - }) - .then(function takeScreenshot() { - common.debug('Take screenshot'); - common.saveScreenshot('./screenshot-' + testSubName + '.png'); }); }); - }); }); diff --git a/test/functional/apps/visualize/_line_chart.js b/test/functional/apps/visualize/_line_chart.js index 0382f070bf4ac..2b186a1f21ba5 100644 --- a/test/functional/apps/visualize/_line_chart.js +++ b/test/functional/apps/visualize/_line_chart.js @@ -52,12 +52,9 @@ bdd.describe('visualize app', function describeIndexTests() { }); bdd.describe('line charts', function indexPatternCreation() { - var testSubName = 'LineChart'; - var vizName1 = 'Visualization ' + testSubName; + var vizName1 = 'Visualization LineChart'; bdd.it('should be able to save and load', function pageHeader() { - - common.debug('Start of test' + testSubName + 'Visualization'); var remote = this.remote; return visualizePage.saveVisualization(vizName1) @@ -90,6 +87,7 @@ bdd.describe('visualize app', function describeIndexTests() { .then(function () { return visualizePage.getLineChartData('fill="#57c17b"') .then(function showData(data) { + common.saveScreenshot('Visualize-line-chart'); var tolerance = 10; // the y-axis scale is 10000 so 10 is 0.1% for (var x = 0; x < data.length; x++) { common.debug('x=' + x + ' expectedChartData[x].split(\' \')[1] = ' + @@ -99,11 +97,6 @@ bdd.describe('visualize app', function describeIndexTests() { } common.debug('Done'); }); - }) - .then(function takeScreenshot() { - // take a snapshot just as an example. - common.debug('Take screenshot'); - common.saveScreenshot('./screenshot-' + testSubName + '.png'); }); }); diff --git a/test/functional/apps/visualize/_metric_chart.js b/test/functional/apps/visualize/_metric_chart.js index 811061858af24..29a4cd96e993f 100644 --- a/test/functional/apps/visualize/_metric_chart.js +++ b/test/functional/apps/visualize/_metric_chart.js @@ -14,11 +14,6 @@ bdd.describe('visualize app', function describeIndexTests() { var toTime = '2015-09-23 18:31:44.000'; bdd.before(function () { - - var testSubName = 'MetricChart'; - common.debug('Start of test' + testSubName + 'Visualization'); - var vizName1 = 'Visualization ' + testSubName; - common.debug('navigateToApp visualize'); return common.navigateToApp('visualize') .then(function () { @@ -34,7 +29,6 @@ bdd.describe('visualize app', function describeIndexTests() { }); }); - bdd.describe('metric chart', function indexPatternCreation() { bdd.it('should show Count', function pageHeader() { @@ -44,6 +38,7 @@ bdd.describe('visualize app', function describeIndexTests() { return common.try(function tryingForTime() { return visualizePage.getMetric() .then(function (metricValue) { + common.saveScreenshot('Visualize-metric-chart'); expect(expectedCount).to.eql(metricValue.split('\n')); }); }); diff --git a/test/functional/apps/visualize/_pie_chart.js b/test/functional/apps/visualize/_pie_chart.js index 424f855698a32..e944678602040 100644 --- a/test/functional/apps/visualize/_pie_chart.js +++ b/test/functional/apps/visualize/_pie_chart.js @@ -60,12 +60,9 @@ bdd.describe('visualize app', function describeIndexTests() { bdd.describe('pie chart', function indexPatternCreation() { - var testSubName = 'PieChart'; - var vizName1 = 'Visualization ' + testSubName; - + var vizName1 = 'Visualization PieChart'; bdd.it('should save and load', function pageHeader() { - common.debug('Start of test' + testSubName + 'Visualization'); var remote = this.remote; return visualizePage.saveVisualization(vizName1) @@ -96,11 +93,8 @@ bdd.describe('visualize app', function describeIndexTests() { .then(function (pieData) { var barHeightTolerance = 1; common.debug('pieData.length = ' + pieData.length); + common.saveScreenshot('Visualize-pie-chart'); expect(pieData.length).to.be(expectedPieChartSliceCount); - }) - .then(function takeScreenshot() { - common.debug('Take screenshot'); - common.saveScreenshot('./screenshot-' + testSubName + '.png'); }); }); @@ -122,7 +116,5 @@ bdd.describe('visualize app', function describeIndexTests() { expect(data.trim().split('\n')).to.eql(expectedTableData); }); }); - - }); }); diff --git a/test/functional/apps/visualize/_tile_map.js b/test/functional/apps/visualize/_tile_map.js index 3693fbc888367..a8dd2d914073c 100644 --- a/test/functional/apps/visualize/_tile_map.js +++ b/test/functional/apps/visualize/_tile_map.js @@ -50,14 +50,10 @@ bdd.describe('visualize app', function describeIndexTests() { }); }); - bdd.describe('tile map chart', function indexPatternCreation() { bdd.it('should save and load, take screenshot', function pageHeader() { - var testSubName = 'TileMap'; - common.debug('Start of test' + testSubName + 'Visualization'); - var vizName1 = 'Visualization ' + testSubName; - // var remote = this.remote; + var vizName1 = 'Visualization TileMap'; return visualizePage.saveVisualization(vizName1) .then(function (message) { @@ -79,14 +75,11 @@ bdd.describe('visualize app', function describeIndexTests() { }) .then(function takeScreenshot() { common.debug('Take screenshot'); - common.saveScreenshot('./screenshot-' + testSubName + '.png'); + common.saveScreenshot('Visualize-site-map'); }); }); bdd.it('should show correct tile map data', function pageHeader() { - var testSubName = 'TileMap'; - common.debug('Start of test' + testSubName + 'Visualization'); - // var remote = this.remote; var expectedTableData = [ 'dn 1,429', 'dp 1,418', '9y 1,215', '9z 1,099', 'dr 1,076', 'dj 982', '9v 938', '9q 722', '9w 475', 'cb 457', 'c2 453', '9x 420', 'dq 399', '9r 396', '9t 274', 'c8 271', 'dh 214', 'b6 207', 'bd 206', 'b7 167', 'f0 141', @@ -107,7 +100,5 @@ bdd.describe('visualize app', function describeIndexTests() { }); }); }); - - }); }); diff --git a/test/functional/apps/visualize/_vertical_bar_chart.js b/test/functional/apps/visualize/_vertical_bar_chart.js index ec399a32879b5..e3cbc9f2366e8 100644 --- a/test/functional/apps/visualize/_vertical_bar_chart.js +++ b/test/functional/apps/visualize/_vertical_bar_chart.js @@ -52,8 +52,7 @@ bdd.describe('visualize app', function describeIndexTests() { }); bdd.describe('vertical bar chart', function indexPatternCreation() { - var testSubName = 'VerticalBarChart'; - var vizName1 = 'Visualization ' + testSubName; + var vizName1 = 'Visualization VerticalBarChart'; bdd.it('should save and load', function pageHeader() { return visualizePage.saveVisualization(vizName1) @@ -75,7 +74,6 @@ bdd.describe('visualize app', function describeIndexTests() { }); }); - bdd.it('should show correct chart, take screenshot', function pageHeader() { var expectedChartValues = [37, 202, 740, 1437, 1371, 751, 188, 31, 42, 202, 683, 1361, 1415, 707, 177, 27, 32, 175, 707, 1408, 1355, 726, 201, 29 @@ -91,17 +89,13 @@ bdd.describe('visualize app', function describeIndexTests() { .then(function showData(data) { common.debug('data=' + data); common.debug('data.length=' + data.length); + common.saveScreenshot('Visualize-vertical-bar-chart'); expect(data).to.eql(expectedChartValues); - }) - .then(function takeScreenshot() { - common.debug('Take screenshot'); - common.saveScreenshot('./screenshot-' + testSubName + '.png'); }); }); bdd.it('should show correct data', function pageHeader() { - var testSubName = 'VerticalBarChart'; // this is only the first page of the tabular data. var expectedChartData = [ 'September 20th 2015, 00:00:00.000 37', 'September 20th 2015, 03:00:00.000 202', diff --git a/test/functional/status_page/index.js b/test/functional/status_page/index.js index 492e1742a56be..5a813e632c89e 100644 --- a/test/functional/status_page/index.js +++ b/test/functional/status_page/index.js @@ -1,4 +1,7 @@ -import { bdd, common } from '../../support'; +import { + bdd, + common +} from '../../support'; var expect = require('expect.js'); @@ -15,6 +18,7 @@ bdd.describe('status page', function () { .findByCssSelector('.plugin_status_breakdown') .getVisibleText() .then(function (text) { + common.saveScreenshot('Status'); expect(text.indexOf('kibana 1.0.0 Ready')).to.be.above(-1); }); }) diff --git a/test/screenshots/baseline/Console-default-request.png b/test/screenshots/baseline/Console-default-request.png new file mode 100644 index 0000000000000..46c39f95c1a5c Binary files /dev/null and b/test/screenshots/baseline/Console-default-request.png differ diff --git a/test/screenshots/baseline/Console-help-collapsed.png b/test/screenshots/baseline/Console-help-collapsed.png new file mode 100644 index 0000000000000..b7b7649b39bee Binary files /dev/null and b/test/screenshots/baseline/Console-help-collapsed.png differ diff --git a/test/screenshots/baseline/Console-help-expanded.png b/test/screenshots/baseline/Console-help-expanded.png new file mode 100644 index 0000000000000..e95e7e2f97ab8 Binary files /dev/null and b/test/screenshots/baseline/Console-help-expanded.png differ diff --git a/test/screenshots/baseline/Dashboard-add-visualizations.png b/test/screenshots/baseline/Dashboard-add-visualizations.png new file mode 100644 index 0000000000000..358d90f949556 Binary files /dev/null and b/test/screenshots/baseline/Dashboard-add-visualizations.png differ diff --git a/test/screenshots/baseline/Dashboard-has-visualizations.png b/test/screenshots/baseline/Dashboard-has-visualizations.png new file mode 100644 index 0000000000000..d17b8687063f2 Binary files /dev/null and b/test/screenshots/baseline/Dashboard-has-visualizations.png differ diff --git a/test/screenshots/baseline/Dashboard-load-saved.png b/test/screenshots/baseline/Dashboard-load-saved.png new file mode 100644 index 0000000000000..e36c2f7ed2958 Binary files /dev/null and b/test/screenshots/baseline/Dashboard-load-saved.png differ diff --git a/test/screenshots/baseline/Dashboard-no-visualizations.png b/test/screenshots/baseline/Dashboard-no-visualizations.png new file mode 100644 index 0000000000000..291a0342a2204 Binary files /dev/null and b/test/screenshots/baseline/Dashboard-no-visualizations.png differ diff --git a/test/screenshots/baseline/Dashboard-set-timepicker.png b/test/screenshots/baseline/Dashboard-set-timepicker.png new file mode 100644 index 0000000000000..bfe6825f8fb36 Binary files /dev/null and b/test/screenshots/baseline/Dashboard-set-timepicker.png differ diff --git a/test/screenshots/baseline/Dashboard-visualization-sizes.png b/test/screenshots/baseline/Dashboard-visualization-sizes.png new file mode 100644 index 0000000000000..d17b8687063f2 Binary files /dev/null and b/test/screenshots/baseline/Dashboard-visualization-sizes.png differ diff --git a/test/screenshots/baseline/Discover-copy-to-clipboard-toast.png b/test/screenshots/baseline/Discover-copy-to-clipboard-toast.png new file mode 100644 index 0000000000000..6b764e08a64c5 Binary files /dev/null and b/test/screenshots/baseline/Discover-copy-to-clipboard-toast.png differ diff --git a/test/screenshots/baseline/Discover-field-data.png b/test/screenshots/baseline/Discover-field-data.png new file mode 100644 index 0000000000000..7addb008d8abd Binary files /dev/null and b/test/screenshots/baseline/Discover-field-data.png differ diff --git a/test/screenshots/baseline/Discover-load-query.png b/test/screenshots/baseline/Discover-load-query.png new file mode 100644 index 0000000000000..240bbd26674d4 Binary files /dev/null and b/test/screenshots/baseline/Discover-load-query.png differ diff --git a/test/screenshots/baseline/Discover-no-results.png b/test/screenshots/baseline/Discover-no-results.png new file mode 100644 index 0000000000000..4eb379994da40 Binary files /dev/null and b/test/screenshots/baseline/Discover-no-results.png differ diff --git a/test/screenshots/baseline/Discover-save-query-toast.png b/test/screenshots/baseline/Discover-save-query-toast.png new file mode 100644 index 0000000000000..85250d09ef234 Binary files /dev/null and b/test/screenshots/baseline/Discover-save-query-toast.png differ diff --git a/test/screenshots/baseline/Discover-share-link.png b/test/screenshots/baseline/Discover-share-link.png new file mode 100644 index 0000000000000..03e166af992b8 Binary files /dev/null and b/test/screenshots/baseline/Discover-share-link.png differ diff --git a/test/screenshots/baseline/Discover-shorten-url-button.png b/test/screenshots/baseline/Discover-shorten-url-button.png new file mode 100644 index 0000000000000..e5fe38df7e66d Binary files /dev/null and b/test/screenshots/baseline/Discover-shorten-url-button.png differ diff --git a/test/screenshots/baseline/Discover-sidebar-collapsed.png b/test/screenshots/baseline/Discover-sidebar-collapsed.png new file mode 100644 index 0000000000000..0e45cdbe16e44 Binary files /dev/null and b/test/screenshots/baseline/Discover-sidebar-collapsed.png differ diff --git a/test/screenshots/baseline/Discover-sidebar-expanded.png b/test/screenshots/baseline/Discover-sidebar-expanded.png new file mode 100644 index 0000000000000..3bdb1a7ecf75e Binary files /dev/null and b/test/screenshots/baseline/Discover-sidebar-expanded.png differ diff --git a/test/screenshots/baseline/Discover-sort-down.png b/test/screenshots/baseline/Discover-sort-down.png new file mode 100644 index 0000000000000..7161e46c294e6 Binary files /dev/null and b/test/screenshots/baseline/Discover-sort-down.png differ diff --git a/test/screenshots/baseline/Discover-syntax-error-toast.png b/test/screenshots/baseline/Discover-syntax-error-toast.png new file mode 100644 index 0000000000000..b52f948ccd445 Binary files /dev/null and b/test/screenshots/baseline/Discover-syntax-error-toast.png differ diff --git a/test/screenshots/baseline/Settings-advanced-tab.png b/test/screenshots/baseline/Settings-advanced-tab.png new file mode 100644 index 0000000000000..3ec0cb5c79927 Binary files /dev/null and b/test/screenshots/baseline/Settings-advanced-tab.png differ diff --git a/test/screenshots/baseline/Settings-indices-column-name-sort-ascending.png b/test/screenshots/baseline/Settings-indices-column-name-sort-ascending.png new file mode 100644 index 0000000000000..1e38e63321c59 Binary files /dev/null and b/test/screenshots/baseline/Settings-indices-column-name-sort-ascending.png differ diff --git a/test/screenshots/baseline/Settings-indices-column-name-sort-descending.png b/test/screenshots/baseline/Settings-indices-column-name-sort-descending.png new file mode 100644 index 0000000000000..9d430c577da7b Binary files /dev/null and b/test/screenshots/baseline/Settings-indices-column-name-sort-descending.png differ diff --git a/test/screenshots/baseline/Settings-indices-column-type-sort-ascending.png b/test/screenshots/baseline/Settings-indices-column-type-sort-ascending.png new file mode 100644 index 0000000000000..b8b46275b746a Binary files /dev/null and b/test/screenshots/baseline/Settings-indices-column-type-sort-ascending.png differ diff --git a/test/screenshots/baseline/Settings-indices-column-type-sort-descending.png b/test/screenshots/baseline/Settings-indices-column-type-sort-descending.png new file mode 100644 index 0000000000000..92c6565f15b80 Binary files /dev/null and b/test/screenshots/baseline/Settings-indices-column-type-sort-descending.png differ diff --git a/test/screenshots/baseline/Settings-indices-confirm-remove-index-pattern.png b/test/screenshots/baseline/Settings-indices-confirm-remove-index-pattern.png new file mode 100644 index 0000000000000..b822f34633b06 Binary files /dev/null and b/test/screenshots/baseline/Settings-indices-confirm-remove-index-pattern.png differ diff --git a/test/screenshots/baseline/Settings-indices-enable-creation.png b/test/screenshots/baseline/Settings-indices-enable-creation.png new file mode 100644 index 0000000000000..2354454c363ad Binary files /dev/null and b/test/screenshots/baseline/Settings-indices-enable-creation.png differ diff --git a/test/screenshots/baseline/Settings-indices-new-index-pattern.png b/test/screenshots/baseline/Settings-indices-new-index-pattern.png new file mode 100644 index 0000000000000..3b1d258f45916 Binary files /dev/null and b/test/screenshots/baseline/Settings-indices-new-index-pattern.png differ diff --git a/test/screenshots/baseline/Settings-indices-paged.png b/test/screenshots/baseline/Settings-indices-paged.png new file mode 100644 index 0000000000000..9822d798f783f Binary files /dev/null and b/test/screenshots/baseline/Settings-indices-paged.png differ diff --git a/test/screenshots/baseline/Settings-indices-result-popularity-saved.png b/test/screenshots/baseline/Settings-indices-result-popularity-saved.png new file mode 100644 index 0000000000000..8fc7a41d039cd Binary files /dev/null and b/test/screenshots/baseline/Settings-indices-result-popularity-saved.png differ diff --git a/test/screenshots/baseline/Settings-indices-result-popularity-updated.png b/test/screenshots/baseline/Settings-indices-result-popularity-updated.png new file mode 100644 index 0000000000000..ad146f72f9908 Binary files /dev/null and b/test/screenshots/baseline/Settings-indices-result-popularity-updated.png differ diff --git a/test/screenshots/baseline/Settings-initial-state.png b/test/screenshots/baseline/Settings-initial-state.png new file mode 100644 index 0000000000000..fb905b57ef15a Binary files /dev/null and b/test/screenshots/baseline/Settings-initial-state.png differ diff --git a/test/screenshots/baseline/Settings-set-timezone.png b/test/screenshots/baseline/Settings-set-timezone.png new file mode 100644 index 0000000000000..70221c500e906 Binary files /dev/null and b/test/screenshots/baseline/Settings-set-timezone.png differ diff --git a/test/screenshots/baseline/Status.png b/test/screenshots/baseline/Status.png new file mode 100644 index 0000000000000..cf1d1e14da880 Binary files /dev/null and b/test/screenshots/baseline/Status.png differ diff --git a/test/screenshots/baseline/Visualize-area-chart-save-toast.png b/test/screenshots/baseline/Visualize-area-chart-save-toast.png new file mode 100644 index 0000000000000..b3480456d5ef6 Binary files /dev/null and b/test/screenshots/baseline/Visualize-area-chart-save-toast.png differ diff --git a/test/screenshots/baseline/Visualize-area-chart.png b/test/screenshots/baseline/Visualize-area-chart.png new file mode 100644 index 0000000000000..c8e5e91659f5b Binary files /dev/null and b/test/screenshots/baseline/Visualize-area-chart.png differ diff --git a/test/screenshots/baseline/Visualize-chart-types.png b/test/screenshots/baseline/Visualize-chart-types.png new file mode 100644 index 0000000000000..012f81e221bea Binary files /dev/null and b/test/screenshots/baseline/Visualize-chart-types.png differ diff --git a/test/screenshots/baseline/Visualize-data-table.png b/test/screenshots/baseline/Visualize-data-table.png new file mode 100644 index 0000000000000..ddde143c517f2 Binary files /dev/null and b/test/screenshots/baseline/Visualize-data-table.png differ diff --git a/test/screenshots/baseline/Visualize-line-chart.png b/test/screenshots/baseline/Visualize-line-chart.png new file mode 100644 index 0000000000000..f15f7a64c938f Binary files /dev/null and b/test/screenshots/baseline/Visualize-line-chart.png differ diff --git a/test/screenshots/baseline/Visualize-metric-chart.png b/test/screenshots/baseline/Visualize-metric-chart.png new file mode 100644 index 0000000000000..1580e4398260e Binary files /dev/null and b/test/screenshots/baseline/Visualize-metric-chart.png differ diff --git a/test/screenshots/baseline/Visualize-pie-chart.png b/test/screenshots/baseline/Visualize-pie-chart.png new file mode 100644 index 0000000000000..c533c05e44797 Binary files /dev/null and b/test/screenshots/baseline/Visualize-pie-chart.png differ diff --git a/test/screenshots/baseline/Visualize-site-map.png b/test/screenshots/baseline/Visualize-site-map.png new file mode 100644 index 0000000000000..f21e5da64c03d Binary files /dev/null and b/test/screenshots/baseline/Visualize-site-map.png differ diff --git a/test/screenshots/baseline/Visualize-vertical-bar-chart.png b/test/screenshots/baseline/Visualize-vertical-bar-chart.png new file mode 100644 index 0000000000000..3d48436c64200 Binary files /dev/null and b/test/screenshots/baseline/Visualize-vertical-bar-chart.png differ diff --git a/test/screenshots/baseline/screenshot-AreaChart.png b/test/screenshots/baseline/screenshot-AreaChart.png deleted file mode 100644 index d5bbbd9b30809..0000000000000 Binary files a/test/screenshots/baseline/screenshot-AreaChart.png and /dev/null differ diff --git a/test/screenshots/baseline/screenshot-Dashboard Test 1.png b/test/screenshots/baseline/screenshot-Dashboard Test 1.png deleted file mode 100644 index 0d09c01f83ce7..0000000000000 Binary files a/test/screenshots/baseline/screenshot-Dashboard Test 1.png and /dev/null differ diff --git a/test/screenshots/baseline/screenshot-DataTable.png b/test/screenshots/baseline/screenshot-DataTable.png deleted file mode 100644 index d1328c28229cf..0000000000000 Binary files a/test/screenshots/baseline/screenshot-DataTable.png and /dev/null differ diff --git a/test/screenshots/baseline/screenshot-LineChart.png b/test/screenshots/baseline/screenshot-LineChart.png deleted file mode 100644 index 5b0a8b9b1d490..0000000000000 Binary files a/test/screenshots/baseline/screenshot-LineChart.png and /dev/null differ diff --git a/test/screenshots/baseline/screenshot-PieChart.png b/test/screenshots/baseline/screenshot-PieChart.png deleted file mode 100644 index b51e7ad69f52b..0000000000000 Binary files a/test/screenshots/baseline/screenshot-PieChart.png and /dev/null differ diff --git a/test/screenshots/baseline/screenshot-TileMap.png b/test/screenshots/baseline/screenshot-TileMap.png deleted file mode 100644 index cdd55dbe73628..0000000000000 Binary files a/test/screenshots/baseline/screenshot-TileMap.png and /dev/null differ diff --git a/test/screenshots/baseline/screenshot-VerticalBarChart.png b/test/screenshots/baseline/screenshot-VerticalBarChart.png deleted file mode 100644 index 819eaf925f2e2..0000000000000 Binary files a/test/screenshots/baseline/screenshot-VerticalBarChart.png and /dev/null differ diff --git a/test/support/pages/common.js b/test/support/pages/common.js index 04f25e6a050ce..18751a9480a89 100644 --- a/test/support/pages/common.js +++ b/test/support/pages/common.js @@ -253,7 +253,7 @@ export default (function () { const testName = (testObj.parent) ? [testObj.parent.name, testObj.name].join('_') : testObj.name; return reason => { const now = Date.now(); - const fileName = `failure_${now}_${testName}.png`; + const fileName = `failure_${now}_${testName}`; return this.saveScreenshot(fileName, true) .then(function () { @@ -266,7 +266,7 @@ export default (function () { try { const directoryName = isFailure ? 'failure' : 'session'; const directoryPath = path.resolve(`test/screenshots/${directoryName}`); - const filePath = path.resolve(directoryPath, fileName); + const filePath = path.resolve(directoryPath, `${fileName}.png`); this.debug(`Taking screenshot "${filePath}"`); const screenshot = await this.remote.takeScreenshot(); diff --git a/utilities/compareScreenshots.js b/utilities/compareScreenshots.js deleted file mode 100644 index af7722b9eb1f9..0000000000000 --- a/utilities/compareScreenshots.js +++ /dev/null @@ -1,43 +0,0 @@ - -const fs = require('fs'); -const path = require('path'); -const imageDiff = require('image-diff'); -const mkdirp = require('mkdirp'); - -function compareScreenshots() { - const SCREENSHOTS_DIR = 'test/screenshots'; - const BASELINE_SCREENSHOTS_DIR = path.resolve(SCREENSHOTS_DIR, 'baseline'); - const DIFF_SCREENSHOTS_DIR = path.resolve(SCREENSHOTS_DIR, 'diff'); - const SESSION_SCREENSHOTS_DIR = path.resolve(SCREENSHOTS_DIR, 'session'); - - // We don't need to create the baseline dir because it's committed. - mkdirp.sync(DIFF_SCREENSHOTS_DIR); - mkdirp.sync(SESSION_SCREENSHOTS_DIR); - - fs.readdir(SESSION_SCREENSHOTS_DIR, (readDirError, files) => { - const screenshots = files.filter(file => file.indexOf('.png') !== -1); - - screenshots.forEach(screenshot => { - const sessionImagePath = path.resolve(SESSION_SCREENSHOTS_DIR, screenshot); - const baselineImagePath = path.resolve(BASELINE_SCREENSHOTS_DIR, screenshot); - const diffImagePath = path.resolve(DIFF_SCREENSHOTS_DIR, screenshot); - - imageDiff.getFullResult({ - actualImage: sessionImagePath, - expectedImage: baselineImagePath, - diffImage: diffImagePath, - shadow: true, - }, (comparisonError, result) => { - if (comparisonError) { - throw comparisonError; - } - - const change = result.percentage; - const changePercentage = (change * 100).toFixed(2); - console.log(`${screenshot} has changed by ${changePercentage}%`); - }); - }); - }); -} - -compareScreenshots(); diff --git a/utilities/templates/visual_regression_gallery.dot b/utilities/templates/visual_regression_gallery.dot new file mode 100644 index 0000000000000..176590aa60660 --- /dev/null +++ b/utilities/templates/visual_regression_gallery.dot @@ -0,0 +1,296 @@ + + + + Kibana Visual Regression Gallery + + + + + + + + +
+ Kibana Visual Regression Gallery +
+ +
+ {{=it.branch}} - {{=it.date}} +
+ + {{~it.comparisons :comparison:index}} +
+
+ ({{=comparison.percentage}}%) {{=comparison.name}} +
+ +
+
Diff
+ +
+ Baseline +
+
+ +
+ +
+ +
+ + + + + +
+ +
+
+
+ {{~}} + + + + + diff --git a/utilities/visual_regression.js b/utilities/visual_regression.js new file mode 100644 index 0000000000000..f1385d8c31a8f --- /dev/null +++ b/utilities/visual_regression.js @@ -0,0 +1,130 @@ + +import bluebird, { + fromNode, + promisify, +} from 'bluebird'; +import dot from 'dot'; +import fs from 'fs'; +import path from 'path'; +import imageDiff from 'image-diff'; +import mkdirp from 'mkdirp'; +import moment from 'moment'; +import SimpleGit from 'simple-git'; + +const readDirAsync = promisify(fs.readdir); +const readFileAsync = promisify(fs.readFile); +const writeFileAsync = promisify(fs.writeFile); + +// Preserve whitespace in our HTML output. +dot.templateSettings.strip = false; + +const templates = dot.process({ + path: path.resolve('./utilities/templates') +}); + +function buildGallery(comparisons) { + const simpleGit = new SimpleGit(); + const asyncBranch = promisify(simpleGit.branch, simpleGit); + + return asyncBranch().then(data => { + const branch = data.current; + + const html = templates.visual_regression_gallery({ + date: moment().format('MMMM Do YYYY, h:mm:ss a'), + branch, + hiddenThreshold: 0, + warningThreshold: 0.03, + comparisons, + }); + + return writeFileAsync( + path.resolve('./test/screenshots/visual_regression_gallery.html'), + html + ); + }); +} + +async function compareScreenshots() { + const SCREENSHOTS_DIR = 'test/screenshots'; + const BASELINE_SCREENSHOTS_DIR = path.resolve(SCREENSHOTS_DIR, 'baseline'); + const DIFF_SCREENSHOTS_DIR = path.resolve(SCREENSHOTS_DIR, 'diff'); + const SESSION_SCREENSHOTS_DIR = path.resolve(SCREENSHOTS_DIR, 'session'); + + // We don't need to create the baseline dir because it's committed. + mkdirp.sync(DIFF_SCREENSHOTS_DIR); + mkdirp.sync(SESSION_SCREENSHOTS_DIR); + const files = await readDirAsync(SESSION_SCREENSHOTS_DIR); + const screenshots = files.filter(file => file.indexOf('.png') !== -1); + + // We'll use this data to build a screenshot gallery in HTML. + return await bluebird.map(screenshots, async screenshot => { + // We're going to load image data and cache it in this object. + const comparison = { + name: screenshot, + change: undefined, + percentage: undefined, + imageData: { + session: undefined, + baseline: undefined, + diff: undefined, + } + }; + + const sessionImagePath = path.resolve( + SESSION_SCREENSHOTS_DIR, + screenshot + ); + + const baselineImagePath = path.resolve( + BASELINE_SCREENSHOTS_DIR, + screenshot + ); + + const diffImagePath = path.resolve( + DIFF_SCREENSHOTS_DIR, + screenshot + ); + + // Diff the images asynchronously. + const diffResult = await fromNode((cb) => { + imageDiff.getFullResult({ + actualImage: sessionImagePath, + expectedImage: baselineImagePath, + diffImage: diffImagePath, + shadow: true, + }, cb); + }); + + const change = diffResult.percentage; + const changePercentage = (change * 100).toFixed(2); + console.log(`(${changePercentage}%) ${screenshot}`); + comparison.percentage = changePercentage; + comparison.change = change; + + // Once the images have been diffed, we can load and store the image data. + comparison.imageData.session = + await readFileAsync(sessionImagePath, 'base64'); + + comparison.imageData.baseline = + await readFileAsync(baselineImagePath, 'base64'); + + comparison.imageData.diff = + await readFileAsync(diffImagePath, 'base64'); + + return comparison; + }); +} + +module.exports = { + run: done => { + compareScreenshots().then(screenshotComparisons => { + // Once all of the data has been loaded, we can build the gallery. + buildGallery(screenshotComparisons).then(() => { + done(); + }); + }, error => { + console.error(error); + done(false); + }); + } +};