diff --git a/.travis.yml b/.travis.yml index 30d72e8d4..d34eec00e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,15 @@ language: node_js node_js: - 6.8.1 sudo: false +addons: + apt: + packages: + - xvfb install: - time npm install - time ./node_modules/bower/bin/bower update +- export DISPLAY=':99.0' +- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & env: global: - secure: |- diff --git a/dist/css/fuelux.css b/dist/css/fuelux.css index 06418018c..65b4ffe83 100644 --- a/dist/css/fuelux.css +++ b/dist/css/fuelux.css @@ -1,5 +1,6 @@ /*! - * Fuel UX v3.16.0 + * Fuel UX EDGE - Built 2017/06/09, 4:48:45 PM + * Previous release: v3.16.0 * Copyright 2012-2017 ExactTarget * Licensed under the BSD-3-Clause license (https://github.com/ExactTarget/fuelux/blob/master/LICENSE) */ diff --git a/dist/css/fuelux.min.css b/dist/css/fuelux.min.css index b2d40e888..7e64c79d9 100644 --- a/dist/css/fuelux.min.css +++ b/dist/css/fuelux.min.css @@ -1,5 +1,6 @@ /*! - * Fuel UX v3.16.0 + * Fuel UX EDGE - Built 2017/06/09, 4:48:45 PM + * Previous release: v3.16.0 * Copyright 2012-2017 ExactTarget * Licensed under the BSD-3-Clause license (https://github.com/ExactTarget/fuelux/blob/master/LICENSE) */ diff --git a/dist/fuelux.zip b/dist/fuelux.zip index d505d6879..336cd8bdf 100644 Binary files a/dist/fuelux.zip and b/dist/fuelux.zip differ diff --git a/dist/js/fuelux.js b/dist/js/fuelux.js index 4e6ad51ce..ec172b5ea 100644 --- a/dist/js/fuelux.js +++ b/dist/js/fuelux.js @@ -1,5 +1,6 @@ /*! - * Fuel UX v3.16.0 + * Fuel UX EDGE - Built 2017/06/09, 4:48:45 PM + * Previous release: v3.16.0 * Copyright 2012-2017 ExactTarget * Licensed under the BSD-3-Clause license (https://github.com/ExactTarget/fuelux/blob/master/LICENSE) */ diff --git a/dist/js/fuelux.min.js b/dist/js/fuelux.min.js index 700163428..c4651e847 100644 --- a/dist/js/fuelux.min.js +++ b/dist/js/fuelux.min.js @@ -1,5 +1,6 @@ /*! - * Fuel UX v3.16.0 + * Fuel UX EDGE - Built 2017/06/09, 4:48:45 PM + * Previous release: v3.16.0 * Copyright 2012-2017 ExactTarget * Licensed under the BSD-3-Clause license (https://github.com/ExactTarget/fuelux/blob/master/LICENSE) */ diff --git a/grunt/config/connect.js b/grunt/config/connect.js index f13fd0ec6..2b7ae23c9 100644 --- a/grunt/config/connect.js +++ b/grunt/config/connect.js @@ -27,6 +27,5 @@ module.exports = function (grunt) { useAvailablePort: true } } - } - -}; \ No newline at end of file + }; +}; diff --git a/grunt/config/jshint.js b/grunt/config/jshint.js index fe30b8e09..fba40e5b7 100644 --- a/grunt/config/jshint.js +++ b/grunt/config/jshint.js @@ -3,6 +3,5 @@ module.exports = { jshintrc: '.jshintrc', // use project defined jshint settings which can be shared with IDEs etc ignores: ['test/data/*.js'] }, - sourceAndDist: ['Gruntfile.js', 'js/*.js', 'dist/fuelux.js'], - tests: ['test/**/*.js', '!test/commonjs-bundle.js'], + sourceAndDist: ['Gruntfile.js', 'js/*.js', 'dist/fuelux.js'] }; diff --git a/grunt/config/shell.js b/grunt/config/shell.js index 49497e7b4..9265cd119 100644 --- a/grunt/config/shell.js +++ b/grunt/config/shell.js @@ -113,6 +113,28 @@ module.exports = function (grunt) { grunt.log.write(command); return command; } + }, + copyToReference: { + command: function copyDistToRef() { + var moveDist = [ + 'rm -rf reference/dist', + 'mkdir reference/dist', + 'cp -R dist/* reference/dist' + ].join(' && '); + grunt.log.write('Copying dist into reference/dist for use in visual regression testing.\n'); + grunt.log.write(moveDist); + + var deleteFluff = [ + 'rm reference/dist/css/fuelux.css.map', + 'rm reference/dist/css/fuelux.min.css', + 'rm reference/dist/fuelux.zip', + 'rm reference/dist/js/fuelux.min.js' + ].join(' && '); + grunt.log.write('\nRemovine .zip and .min files to save space in repo'); + grunt.log.write(deleteFluff); + + return moveDist + ' && ' + deleteFluff; + } } }; }; diff --git a/grunt/config/watch.js b/grunt/config/watch.js index fe6f1ff03..fad8e41dd 100644 --- a/grunt/config/watch.js +++ b/grunt/config/watch.js @@ -43,7 +43,7 @@ module.exports = { ] }, less: { - files: ['fonts/**', + files: ['fonts/**', 'less/**'], options: { livereload: true @@ -65,9 +65,9 @@ module.exports = { tasks: ['distcssdev'] }, dist: { - files: ['fonts/**', + files: ['fonts/**', 'grunt/**', - 'js/**', + 'js/**', 'less/**'], options: { livereload: true @@ -81,4 +81,4 @@ module.exports = { }, tasks: [] } -}; \ No newline at end of file +}; diff --git a/grunt/tasks/release.js b/grunt/tasks/release.js index ab8aea573..b2fc440c9 100644 --- a/grunt/tasks/release.js +++ b/grunt/tasks/release.js @@ -77,9 +77,22 @@ module.exports = function (grunt) { grunt.config('banner', '<%= bannerRelease %>'); // Run dist again to grab the latest version numbers. Yeah, we're running it twice... ¯\_(ツ)_/¯ - grunt.task.run(['bump-only:' + grunt.config('release.buildSemVerType'), 'replace:readme', 'replace:packageJs', 'dist', - 'shell:addReleaseFiles', 'prompt:commit', 'prompt:tag', 'prompt:pushLocalBranchToUpstream', - 'prompt:pushTagToUpstream', 'prompt:uploadToCDN', 'prompt:pushLocalBranchToUpstreamMaster', 'shell:publishToNPM', 'prompt:generatelogs']); + grunt.task.run([ + 'bump-only:' + grunt.config('release.buildSemVerType'), + 'replace:readme', + 'replace:packageJs', + 'dist', + 'shell:addReleaseFiles', + 'prompt:commit', + 'prompt:tag', + 'prompt:pushLocalBranchToUpstream', + 'prompt:pushTagToUpstream', + 'prompt:uploadToCDN', + 'prompt:pushLocalBranchToUpstreamMaster', + 'shell:publishToNPM', + 'shell:copyToReference', + 'prompt:generatelogs' + ]); }); }; diff --git a/grunt/tasks/serve.js b/grunt/tasks/serve.js index 314e20e77..355072227 100644 --- a/grunt/tasks/serve.js +++ b/grunt/tasks/serve.js @@ -1,22 +1,18 @@ -module.exports = function(grunt) { - - /* ------------- - SERVE - ------------- */ - // default serve task that runs tests and builds and tests dist by default. - grunt.registerTask('serve', 'Test, build, serve files. (~20s)', function () { +module.exports = function serveTasks (grunt) { + // runs tests and builds and tests dist by default. + grunt.registerTask('serve', 'Test, build, serve files. (~20s)', function serve () { var tasks = ['test', 'servedist']; grunt.task.run(tasks); }); // serve task that runs tests and builds and tests dist by default (~20s). - grunt.registerTask('serveslow', 'Serve files. Run all tests. Does not build. (~20s)', function () { + grunt.registerTask('serveslow', 'Serve files. Run all tests. Does not build. (~20s)', function serveslow () { var tasks = ['connect:server', 'test', 'watch:source']; grunt.task.run(tasks); }); - //Fastest serve command for freely slinging code (no tests will run by default). - grunt.registerTask('servefast', 'Serve the files (no watch), --test to run minimal tests. (~0s)', function () { + // Fastest serve command for freely slinging code (no tests will run by default). + grunt.registerTask('servefast', 'Serve the files (no watch), --test to run minimal tests. (~0s)', function servefast () { grunt.task.run(['connect:server']); if (grunt.option('test')) { @@ -27,7 +23,7 @@ module.exports = function(grunt) { }); // Fastest serve command when you're working on LESS - grunt.registerTask('serveless', 'Compile LESS and serve the files. pass --tests to run test. (~3s)', function () { + grunt.registerTask('serveless', 'Compile LESS and serve the files. pass --tests to run test. (~3s)', function serveless () { grunt.task.run(['distcss']); if (grunt.option('test')) { @@ -46,27 +42,25 @@ module.exports = function(grunt) { }); // Complies the less files into the -dev versions, does not overwrite the main css files. - grunt.registerTask('servedev', 'Serve the files with no "dist" build or tests. Optional --no-less to also disable compiling less into css.', function() { - if (! grunt.option('no-less') ) { + grunt.registerTask('servedev', 'Serve the files with no "dist" build or tests. Optional --no-less to also disable compiling less into css.', function servedev () { + if ( !grunt.option('no-less') ) { grunt.task.run(['distcssdev']); } grunt.task.run(['connect:server', 'watch:cssdev']); }); // same as `grunt serve` but tests default to being off - grunt.registerTask('servedist', 'Compile and serve everything, pass --test to run tests. (~7s)', function () { + grunt.registerTask('servedist', 'Compile and serve everything, pass --test to run tests. (~7s)', function servedist () { grunt.task.run(['dist']); - //start up the servers here so we can run tests if appropriate + // start up the servers here so we can run tests if appropriate grunt.task.run(['connect:server']); grunt.task.run(['connect:testServer']); if (grunt.option('test')) { - grunt.task.run(['browserify:commonjs','qunit:dist', 'watch:full']); + grunt.task.run(['browserify:commonjs', 'qunit:dist', 'watch:full']); } else { grunt.task.run(['watch:dist']); } }); - - -}; \ No newline at end of file +}; diff --git a/index.html b/index.html index 7bf7079a7..414942a78 100644 --- a/index.html +++ b/index.html @@ -57,53 +57,6 @@

Checkboxes

-
-
-
- -
-
- -
-
- -
-
- -
-
- -
- - - - -
-
diff --git a/reference/dist/templates/handlebars/fuelux/tree.hbs b/reference/dist/templates/handlebars/fuelux/tree.hbs new file mode 100644 index 000000000..47b3da241 --- /dev/null +++ b/reference/dist/templates/handlebars/fuelux/tree.hbs @@ -0,0 +1,29 @@ +
    + + + + + {{#if initialLoaderHTML}}{{initialLoaderHTML}}{{else}}{{#if loaderHTML }}{{loaderHTML}}{{else}}{{/if}}{{/if}} +
\ No newline at end of file diff --git a/reference/dist/templates/handlebars/fuelux/wizard.hbs b/reference/dist/templates/handlebars/fuelux/wizard.hbs new file mode 100644 index 000000000..2e016ce85 --- /dev/null +++ b/reference/dist/templates/handlebars/fuelux/wizard.hbs @@ -0,0 +1,21 @@ +
+
+
    + {{#each steps}} +
  • {{stepBadge}}{{#if secondaryText}}

    {{/if}}{{stepLabel}}{{#if secondaryText}}

    {{secondaryText}}
    {{/if}}
  • + {{/each}} +
+
+
+ + +
+
+ {{#each steps}} +
+ {{#if title}}

{{title}}

{{/if}} + {{{content}}} +
+ {{/each}} +
+
\ No newline at end of file diff --git a/reference/dist/templates/underscore/bootstrap/button-group.html b/reference/dist/templates/underscore/bootstrap/button-group.html new file mode 100644 index 000000000..cca266587 --- /dev/null +++ b/reference/dist/templates/underscore/bootstrap/button-group.html @@ -0,0 +1,11 @@ + +
+ +
+
+ + +
+ <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> +
+
diff --git a/reference/dist/templates/underscore/bootstrap/button.html b/reference/dist/templates/underscore/bootstrap/button.html new file mode 100644 index 000000000..5c2fb4d6e --- /dev/null +++ b/reference/dist/templates/underscore/bootstrap/button.html @@ -0,0 +1,8 @@ + +
+ +
+ + <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> +
+
diff --git a/reference/dist/templates/underscore/bootstrap/file-button.html b/reference/dist/templates/underscore/bootstrap/file-button.html new file mode 100644 index 000000000..44cbcc9ef --- /dev/null +++ b/reference/dist/templates/underscore/bootstrap/file-button.html @@ -0,0 +1,8 @@ + +
+ + <% if(horizontal) {%>
<% } %> + required <% } %><% if(readonly) {%> readonly <% } %><% if(isDisabled) {%> disabled <% } %>> + <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> + <% if(horizontal) {%>
<% } %> +
\ No newline at end of file diff --git a/reference/dist/templates/underscore/bootstrap/input-with-button-dropdown.html b/reference/dist/templates/underscore/bootstrap/input-with-button-dropdown.html new file mode 100644 index 000000000..9687d3d4e --- /dev/null +++ b/reference/dist/templates/underscore/bootstrap/input-with-button-dropdown.html @@ -0,0 +1,18 @@ + +
+ + <% if(horizontal) {%>
<% } %> +
+ <% if(placement=="appended") { %> required <% } %><% if(readonly) {%> readonly <% } %><% if(isDisabled) {%> disabled <% } %>/><% } %> +
+ + +
+ <% if(placement=="prepended") { %> required <% } %><% if(readonly) {%> readonly <% } %><% if(isDisabled) {%> disabled <% } %>/><% } %> +
+ <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> + <% if(horizontal) {%>
<% } %> +
\ No newline at end of file diff --git a/reference/dist/templates/underscore/bootstrap/input-with-checkbox.html b/reference/dist/templates/underscore/bootstrap/input-with-checkbox.html new file mode 100644 index 000000000..97a74d63f --- /dev/null +++ b/reference/dist/templates/underscore/bootstrap/input-with-checkbox.html @@ -0,0 +1,14 @@ + +
+ + <% if(horizontal) {%>
<% } %> +
+ <% if(placement=="appended") { %> required <% } %><% if(readonly) {%> readonly <% } %><% if(isDisabled) {%> disabled <% } %> /><% } %> + + <% if(placement=="prepended") { %> required <% } %><% if(readonly) {%> readonly <% } %><% if(isDisabled) {%> disabled <% } %> /><% } %> +
+ <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> + <% if(horizontal) {%>
<% } %> +
\ No newline at end of file diff --git a/reference/dist/templates/underscore/bootstrap/input-with-text.html b/reference/dist/templates/underscore/bootstrap/input-with-text.html new file mode 100644 index 000000000..01b580969 --- /dev/null +++ b/reference/dist/templates/underscore/bootstrap/input-with-text.html @@ -0,0 +1,12 @@ + +
+ + <% if(horizontal) {%>
<% } %> +
+ <% if(prepend) { %><%= prepend %><% } %> + required <% } %><% if(readonly) {%> readonly <% } %><% if(isDisabled) {%> disabled <% } %> /> + <% if(append) { %><%= append %><% } %> +
+ <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> + <% if(horizontal) {%>
<% } %> +
diff --git a/reference/dist/templates/underscore/bootstrap/input.html b/reference/dist/templates/underscore/bootstrap/input.html new file mode 100644 index 000000000..ef00c4d1c --- /dev/null +++ b/reference/dist/templates/underscore/bootstrap/input.html @@ -0,0 +1,8 @@ + +
+ + <% if(horizontal) {%>
<% } %> + required <% } %><% if(readonly) {%> readonly <% } %><% if(isDisabled) {%> disabled <% } %>> + <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> + <% if(horizontal) {%>
<% } %> +
diff --git a/reference/dist/templates/underscore/bootstrap/select.html b/reference/dist/templates/underscore/bootstrap/select.html new file mode 100644 index 000000000..7988ba406 --- /dev/null +++ b/reference/dist/templates/underscore/bootstrap/select.html @@ -0,0 +1,10 @@ + +
+ +
+ + <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> +
+
diff --git a/reference/dist/templates/underscore/bootstrap/textarea.html b/reference/dist/templates/underscore/bootstrap/textarea.html new file mode 100644 index 000000000..0012caad7 --- /dev/null +++ b/reference/dist/templates/underscore/bootstrap/textarea.html @@ -0,0 +1,8 @@ + +
+ + <% if(horizontal) {%>
<% } %> + + <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> + <% if(horizontal) {%>
<% } %> +
diff --git a/reference/dist/templates/underscore/fuelux/checkboxes-inline.html b/reference/dist/templates/underscore/fuelux/checkboxes-inline.html new file mode 100644 index 000000000..4eca5ec80 --- /dev/null +++ b/reference/dist/templates/underscore/fuelux/checkboxes-inline.html @@ -0,0 +1,11 @@ + +
+ + +
+ <% _.each(checkboxes, function(checkbox, i){ %><% }); %> + <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> +
+
\ No newline at end of file diff --git a/reference/dist/templates/underscore/fuelux/checkboxes.html b/reference/dist/templates/underscore/fuelux/checkboxes.html new file mode 100644 index 000000000..aeb93469e --- /dev/null +++ b/reference/dist/templates/underscore/fuelux/checkboxes.html @@ -0,0 +1,13 @@ + +
+ +
+ <% _.each(checkboxes, function(checkbox, i){ %>
+ +
<% }); %> + <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> +
+
diff --git a/reference/dist/templates/underscore/fuelux/input-with-combobox.html b/reference/dist/templates/underscore/fuelux/input-with-combobox.html new file mode 100644 index 000000000..50651cc86 --- /dev/null +++ b/reference/dist/templates/underscore/fuelux/input-with-combobox.html @@ -0,0 +1,17 @@ + +
+ + <% if(horizontal) {%>
<% } %> +
input-append<% } else { %>input-prepend<% } %> dropdown combobox<% if(inputsize.length > 0) {%> input-group-<%= inputsize %><% } %>" data-initialize="combobox" id="<%= id %>"> + <% if(placement=="appended") { %> required <% } %><% if(readonly) {%> readonly <% } %><% if(isDisabled) {%> disabled <% } %> /><% } %> +
+ + +
+ <% if(placement=="prepended") { %> required <% } %><% if(readonly) {%> readonly <% } %><% if(isDisabled) {%> disabled <% } %> /><% } %> +
+ <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> + <% if(horizontal) {%>
<% } %> +
diff --git a/reference/dist/templates/underscore/fuelux/radios-inline.html b/reference/dist/templates/underscore/fuelux/radios-inline.html new file mode 100644 index 000000000..ea2b96863 --- /dev/null +++ b/reference/dist/templates/underscore/fuelux/radios-inline.html @@ -0,0 +1,11 @@ + +
+ + +
+ <% _.each(radios, function(radio, i){ %><% }); %> + <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> +
+
\ No newline at end of file diff --git a/reference/dist/templates/underscore/fuelux/radios.html b/reference/dist/templates/underscore/fuelux/radios.html new file mode 100644 index 000000000..8e7b4329d --- /dev/null +++ b/reference/dist/templates/underscore/fuelux/radios.html @@ -0,0 +1,13 @@ + +
+ +
+ <% _.each(radios, function(radio, i){ %>
+ +
<% }); %> + <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> +
+
diff --git a/reference/dist/templates/underscore/fuelux/search.html b/reference/dist/templates/underscore/fuelux/search.html new file mode 100644 index 000000000..8a671257c --- /dev/null +++ b/reference/dist/templates/underscore/fuelux/search.html @@ -0,0 +1,17 @@ + +
+ + <% if(horizontal) {%>
<% } %> + + <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> + <% if(horizontal) {%>
<% } %> +
diff --git a/reference/dist/templates/underscore/fuelux/selectlist.html b/reference/dist/templates/underscore/fuelux/selectlist.html new file mode 100644 index 000000000..649905979 --- /dev/null +++ b/reference/dist/templates/underscore/fuelux/selectlist.html @@ -0,0 +1,18 @@ + +
+ +
+
+ + + +
+ <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> +
+
diff --git a/reference/dist/templates/underscore/fuelux/spinbox.html b/reference/dist/templates/underscore/fuelux/spinbox.html new file mode 100644 index 000000000..7da427148 --- /dev/null +++ b/reference/dist/templates/underscore/fuelux/spinbox.html @@ -0,0 +1,18 @@ + +
+ + class="col-sm-10"<% } %>> +
+ required <% } %><% if(readonly) {%> readonly <% } %><% if(isDisabled) {%> disabled <% } %>> +
+ + +
+
+ <% if (helptext.length > 0) { %>

<%= helptext %>

<% } %> +
+
diff --git a/reference/markup/README.md b/reference/markup/README.md new file mode 100644 index 000000000..34e57b75a --- /dev/null +++ b/reference/markup/README.md @@ -0,0 +1,3 @@ +The contents of this folder (/reference/markup) are the Source of Truth™ for how Fuel UX markup should look (unless someone forgets to change them when The Truth changes 😉). + +Ideally the output of all Handlebars templates, etc, would be compared in some way against these files. \ No newline at end of file diff --git a/markup/checkbox-inline-no-js.html b/reference/markup/checkbox-inline-no-js.html similarity index 100% rename from markup/checkbox-inline-no-js.html rename to reference/markup/checkbox-inline-no-js.html diff --git a/markup/checkbox-inline.html b/reference/markup/checkbox-inline.html similarity index 100% rename from markup/checkbox-inline.html rename to reference/markup/checkbox-inline.html diff --git a/markup/checkbox-no-js-variations.txt b/reference/markup/checkbox-no-js-variations.txt similarity index 100% rename from markup/checkbox-no-js-variations.txt rename to reference/markup/checkbox-no-js-variations.txt diff --git a/markup/checkbox-no-js.html b/reference/markup/checkbox-no-js.html similarity index 100% rename from markup/checkbox-no-js.html rename to reference/markup/checkbox-no-js.html diff --git a/markup/checkbox-variations.txt b/reference/markup/checkbox-variations.txt similarity index 100% rename from markup/checkbox-variations.txt rename to reference/markup/checkbox-variations.txt diff --git a/markup/checkbox.html b/reference/markup/checkbox.html similarity index 100% rename from markup/checkbox.html rename to reference/markup/checkbox.html diff --git a/markup/combobox-variations.txt b/reference/markup/combobox-variations.txt similarity index 100% rename from markup/combobox-variations.txt rename to reference/markup/combobox-variations.txt diff --git a/markup/combobox.html b/reference/markup/combobox.html similarity index 100% rename from markup/combobox.html rename to reference/markup/combobox.html diff --git a/markup/datepicker.html b/reference/markup/datepicker.html similarity index 100% rename from markup/datepicker.html rename to reference/markup/datepicker.html diff --git a/markup/infinite-scroll.html b/reference/markup/infinite-scroll.html similarity index 100% rename from markup/infinite-scroll.html rename to reference/markup/infinite-scroll.html diff --git a/markup/loader-variations.txt b/reference/markup/loader-variations.txt similarity index 100% rename from markup/loader-variations.txt rename to reference/markup/loader-variations.txt diff --git a/markup/loader.html b/reference/markup/loader.html similarity index 100% rename from markup/loader.html rename to reference/markup/loader.html diff --git a/markup/pillbox-variations.txt b/reference/markup/pillbox-variations.txt similarity index 100% rename from markup/pillbox-variations.txt rename to reference/markup/pillbox-variations.txt diff --git a/markup/pillbox-with-pills.html b/reference/markup/pillbox-with-pills.html similarity index 100% rename from markup/pillbox-with-pills.html rename to reference/markup/pillbox-with-pills.html diff --git a/markup/pillbox.html b/reference/markup/pillbox.html similarity index 100% rename from markup/pillbox.html rename to reference/markup/pillbox.html diff --git a/markup/placard-header-footer.html b/reference/markup/placard-header-footer.html similarity index 100% rename from markup/placard-header-footer.html rename to reference/markup/placard-header-footer.html diff --git a/markup/placard-variations.txt b/reference/markup/placard-variations.txt similarity index 100% rename from markup/placard-variations.txt rename to reference/markup/placard-variations.txt diff --git a/markup/placard.html b/reference/markup/placard.html similarity index 100% rename from markup/placard.html rename to reference/markup/placard.html diff --git a/markup/radio-inline-no-js.html b/reference/markup/radio-inline-no-js.html similarity index 100% rename from markup/radio-inline-no-js.html rename to reference/markup/radio-inline-no-js.html diff --git a/markup/radio-inline.html b/reference/markup/radio-inline.html similarity index 100% rename from markup/radio-inline.html rename to reference/markup/radio-inline.html diff --git a/markup/radio-no-js-variations.txt b/reference/markup/radio-no-js-variations.txt similarity index 100% rename from markup/radio-no-js-variations.txt rename to reference/markup/radio-no-js-variations.txt diff --git a/markup/radio-no-js.html b/reference/markup/radio-no-js.html similarity index 100% rename from markup/radio-no-js.html rename to reference/markup/radio-no-js.html diff --git a/markup/radio-variations.txt b/reference/markup/radio-variations.txt similarity index 100% rename from markup/radio-variations.txt rename to reference/markup/radio-variations.txt diff --git a/markup/radio.html b/reference/markup/radio.html similarity index 100% rename from markup/radio.html rename to reference/markup/radio.html diff --git a/markup/repeater-variations.txt b/reference/markup/repeater-variations.txt similarity index 100% rename from markup/repeater-variations.txt rename to reference/markup/repeater-variations.txt diff --git a/markup/repeater.html b/reference/markup/repeater.html similarity index 100% rename from markup/repeater.html rename to reference/markup/repeater.html diff --git a/markup/scheduler.html b/reference/markup/scheduler.html similarity index 100% rename from markup/scheduler.html rename to reference/markup/scheduler.html diff --git a/markup/search.html b/reference/markup/search.html similarity index 100% rename from markup/search.html rename to reference/markup/search.html diff --git a/markup/selectlist-variations.txt b/reference/markup/selectlist-variations.txt similarity index 100% rename from markup/selectlist-variations.txt rename to reference/markup/selectlist-variations.txt diff --git a/markup/selectlist.html b/reference/markup/selectlist.html similarity index 100% rename from markup/selectlist.html rename to reference/markup/selectlist.html diff --git a/markup/spinbox-variations.txt b/reference/markup/spinbox-variations.txt similarity index 100% rename from markup/spinbox-variations.txt rename to reference/markup/spinbox-variations.txt diff --git a/markup/spinbox.html b/reference/markup/spinbox.html similarity index 100% rename from markup/spinbox.html rename to reference/markup/spinbox.html diff --git a/markup/tree-folders-selectable.html b/reference/markup/tree-folders-selectable.html similarity index 100% rename from markup/tree-folders-selectable.html rename to reference/markup/tree-folders-selectable.html diff --git a/markup/tree.html b/reference/markup/tree.html similarity index 100% rename from markup/tree.html rename to reference/markup/tree.html diff --git a/markup/wizard-variations.txt b/reference/markup/wizard-variations.txt similarity index 100% rename from markup/wizard-variations.txt rename to reference/markup/wizard-variations.txt diff --git a/markup/wizard.html b/reference/markup/wizard.html similarity index 100% rename from markup/wizard.html rename to reference/markup/wizard.html diff --git a/test/REGRESSION_TESTING.md b/test/REGRESSION_TESTING.md new file mode 100644 index 000000000..0c72b05e3 --- /dev/null +++ b/test/REGRESSION_TESTING.md @@ -0,0 +1,70 @@ +# Overview +We use [Niffy](https://segment.com/blog/perceptual-diffing-with-niffy/) for regression testing. Niffy is built on top of Nightmare, and Mocha + Chai. + +Niffy compares the current code with the contents of the reference folder. + +The regression tests require an express server to be spun up and render handlebars templates on the server side so that what is served to the page is static HTML. This is because Fuel UX is declarative and some components either initialize on page load or on user interaction (eg. checkbox). In order to accomplish this, the component has to be rendered and ready on pageload when Fuel UX scrapes the page looking for components to initialize. + +The Fuel UX Handlebars templates are used to accomplish this. + +The test/regression folder has a separate file for each Fuel UX asset. + +The regression tests will look at either the local dev code (from `js/*` or `dist/css/fuelux.css`) or will look at the reference code in `reference/dist/`. Ideally the reference code will match the last prod release. Upon Fuel UX release the code from `/dist/` is copied into `/reference/dist/`. + +# Updating reference with intentional changes +If a change intends to change the look of an asset, you will need: + +1. Make a build (`npm build`) +2. Run `npm test` +3. View the failures and ensure they are the expected failures (and that no non-expected failures occurred) +4. Run `npm updatereferences` +5. Run `npm test` again to make sure all pass + +Further changes tested against this new output will now ensure that the new change does not revert. + +# False Positives +Because of "visual noise" you can not set the Threshold to `0`. If you do, 2/3 of the time it will "fail" simply due to a few errant pixels of noise (around shadows or gradients etc). + +Currently the visual buffer in TravisCI is set to 1024x768 (see `.travis.yml` file for this setting), which is 786,432 pixels. 0.001% of that is slightly less than eight pixels. Most visual noise we observed was about 3 pixels. Running a test on `http://localhost:8000/checkbox` where we set the top-left border-radius to 0px instead of 4px resulted in a 0.01% (79px) difference. + +If you get false positives more than 1% of the time, look at the number of pixels by which it is failing (When it fails it will tell you by what amount, something like "Error: 0.01% different, open /tmp/niffy/checkbox/diff.png") and change the threshold to the absolute minimum you can without risking false negatives. + +Do not ever set the threshold over `0.009%` as this will result in false negatives of the worst kind. You will have a change, it will tell you you don't have a change, and you won't be likely to ever notice the change unless you are specifically looking for it. Arrow buttons on spinboxes have previously had mis-rounded corners that no one noticed (but looked horrible _if_ you were actually looking at them) for over 6 months. It was just these sorts of subtle errors that we implemented visual regression testing to catch. The worst possible thing that could happen is that we set up visual regression testing intended to catch imperceptible errors and then _tell it to ignore imperceptible errors_. You have been warned. + +# Debugging Travis CI +When TravisCI was erring out on Niffy, Woodward was able to run Travis locally through Docker: + +1. [Install and setup Docker + Travis](https://docs.travis-ci.com/user/common-build-problems/#Troubleshooting-Locally-in-a-Docker-Image) +2. Copy/paste the following into terminal in a directory without a current fuelux clone: +``` +git clone --depth=50 --branch=master https://github.com/exacttarget/fuelux + +cd fuelux/ + +git fetch origin +refs/pull/1990/merge + +git checkout -qf FETCH_HEAD + +export DEBIAN_FRONTEND=noninteractive + +sudo apt-get install libssl1.0.0 + +sudo -E apt-get -yq update &>> ~/apt-get-update.log + +sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install xvfb + +sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install xvfb + +nvm install 6.8.1 + +npm install + +./node_modules/bower/bin/bower update + +export DISPLAY=':99.0' + +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + +npm test + +``` diff --git a/test/mocha.js b/test/mocha.js new file mode 100644 index 000000000..188852abc --- /dev/null +++ b/test/mocha.js @@ -0,0 +1,41 @@ +/* global describe:false, it:false, before:false, after:false */ + +/* mocha tests for Niffy go here */ +// var express = require('express'); +// var exphbs = require('express-handlebars'); +// var path = require('path'); + +var server = require('./regression/server.js'); + +// var should = require('chai').should(); +var Niffy = require('niffy'); + +var EIGHT_PIXELS = 0.00102; + +describe('Fuel UX 3', function testFuelUX3 () { + var basehost = 'http://localhost:8000'; + var testhost = 'http://localhost:8013'; + var niffy; + var devServer; + var refServer; + + before(function instantiateNiffy () { + devServer = server.getServer(8000); + refServer = server.getServer(8013); + niffy = new Niffy(basehost, testhost, { show: true, threshold: EIGHT_PIXELS }); + }); + after(function* stopAll () { + devServer.close(); + refServer.close(); + yield niffy.end(); + }); + + describe('Components', function testComponents () { + /** + * Top level. + */ + it('/checkbox', function* testCheckbox () { + yield niffy.test('/checkbox'); + }); + }); +}); diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 000000000..88e074673 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1,3 @@ +--slow 10s +--timeout 200s +--require co-mocha \ No newline at end of file diff --git a/test/regression/app.js b/test/regression/app.js new file mode 100644 index 000000000..38abc76f9 --- /dev/null +++ b/test/regression/app.js @@ -0,0 +1,5 @@ +// start with `npm run regressionservers` +var server = require('./server'); + +server.getServer(8000); +server.getServer(8013); diff --git a/test/regression/checkbox.hbs b/test/regression/checkbox.hbs new file mode 100644 index 000000000..74bb5dd85 --- /dev/null +++ b/test/regression/checkbox.hbs @@ -0,0 +1,15 @@ +
+

Checkbox

+
+
+ {{#each checkboxen}} + {{> checkbox this}} + {{/each}} +
+
+ {{#each inlinecheckboxen}} + {{> checkbox this}} + {{/each}} +
+
+
diff --git a/test/regression/config/checkbox.js b/test/regression/config/checkbox.js new file mode 100644 index 000000000..b441f8622 --- /dev/null +++ b/test/regression/config/checkbox.js @@ -0,0 +1,22 @@ +module.exports = { + checkboxen: [ + {checkboxes: [ + {id: 'checkbox1', label: 'Custom checkbox unchecked on page load'}, + {id: 'checkbox2', label: 'Custom checkbox checked on page load', checked: true}, + {id: 'checkbox3', label: 'Disabled custom checkbox unchecked on page load', disabled: true}, + {id: 'checkbox4', label: 'Disabled custom checkbox checked on page load', checked: true, disabled: true} + ]} + ], + inlinecheckboxen: [ + { + id: 'checkboxes-inline', + inline: true, + checkboxes: [ + {id: 'myCustomInlineCheckbox1', label: '1, 2, buckle my shoe', checked: true}, + {id: 'myCustomInlineCheckbox2', label: '3, 4, shut the door'}, + {id: 'myCustomInlineCheckbox3', label: '5, 6, pick up sticks', disabled: true}, + {id: 'myCustomInlineCheckbox4', label: '7, 8, lay them straight', checked: true, disabled: true} + ] + } + ] +}; diff --git a/test/regression/main.hbs b/test/regression/main.hbs new file mode 100644 index 000000000..a30c569a6 --- /dev/null +++ b/test/regression/main.hbs @@ -0,0 +1,64 @@ + + + + + Fuel UX 3 + + + + + + + + + + + +
+ {{{body}}} +
+ + + \ No newline at end of file diff --git a/test/regression/server.js b/test/regression/server.js new file mode 100644 index 000000000..38cd02954 --- /dev/null +++ b/test/regression/server.js @@ -0,0 +1,41 @@ +module.exports = { + getServer: function getServer (P) { + var PORT = P || process.env.PORT || 8000; + var isReference = (PORT === 8000); + var partialsDir = isReference ? './reference/dist/templates/handlebars/fuelux' : './templates/handlebars/fuelux'; + + process.title = (isReference) ? 'referenceServer' : 'devServer'; + + var express = require('express'); + var app = express(); + var exphbs = require('express-handlebars'); + + app.engine('.hbs', + exphbs({ + extname: '.hbs', + defaultLayout: 'main', + layoutsDir: './test/regression/', + partialsDir: partialsDir + }) + ); + + app.set('view engine', '.hbs'); + app.set('views', './test/regression/'); + + var path = require('path'); + app.use(express.static(path.join(__dirname, '../../'))); + + app.get('/checkbox', function renderCheckboxPage (req, res) { + var checkboxData = require('./config/checkbox.js'); + checkboxData.isReference = isReference; + res.render('./checkbox', checkboxData); + }); + + var server = app.listen(PORT, function listen () { + console.log('info', 'Regression test server listening on port ' + server.address().port + '. isReference: ' + isReference); + }); + + return server; + } +}; +