diff --git a/grunt/config/concat.js b/grunt/config/concat.js index 6516e175..07e4b615 100644 --- a/grunt/config/concat.js +++ b/grunt/config/concat.js @@ -15,7 +15,8 @@ module.exports = { 'src/html/HtmlReporter.js', 'src/html/HtmlSpecFilter.js', 'src/html/ResultsNode.js', - 'src/html/QueryString.js' + 'src/html/QueryString.js', + 'src/html/**/*.js' ], dest: 'lib/jasmine-core/jasmine-html.js' }, diff --git a/lib/jasmine-core/jasmine-html.js b/lib/jasmine-core/jasmine-html.js index f77c75e1..debec5e2 100644 --- a/lib/jasmine-core/jasmine-html.js +++ b/lib/jasmine-core/jasmine-html.js @@ -25,6 +25,7 @@ jasmineRequire.html = function(j$) { j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); j$.QueryString = jasmineRequire.QueryString(); j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); + j$.matchers.toHaveClass = jasmineRequire.toHaveClass(j$); }; jasmineRequire.HtmlReporter = function(j$) { @@ -516,3 +517,37 @@ jasmineRequire.QueryString = function() { return QueryString; }; + +jasmineRequire.toHaveClass = function(j$) { + /** + * {@link expect} the actual value to be a DOM element that has the expected class + * @function + * @name matchers#toHaveClass + * @param {Object} expected - The class name to test for + * @example + * var el = document.createElement('div'); + * el.className = 'foo bar baz'; + * expect(el).toHaveClass('bar'); + */ + function toHaveClass(util, customEqualityTesters) { + return { + compare: function(actual, expected) { + if (!isElement(actual)) { + throw new Error(j$.pp(actual) + ' is not a DOM element'); + } + + return { + pass: actual.classList.contains(expected) + }; + } + }; + } + + function isElement(maybeEl) { + return maybeEl && + maybeEl.classList && + j$.isFunction_(maybeEl.classList.contains); + } + + return toHaveClass; +}; diff --git a/spec/html/matchers/toHaveClassSpec.js b/spec/html/matchers/toHaveClassSpec.js new file mode 100644 index 00000000..f4d1b02b --- /dev/null +++ b/spec/html/matchers/toHaveClassSpec.js @@ -0,0 +1,48 @@ +describe('toHaveClass', function() { + it('fails for a DOM element that lacks the expected class', function() { + var matcher = jasmineUnderTest.matchers.toHaveClass(), + result = matcher.compare(document.createElement('div'), 'foo'); + + expect(result.pass).toBe(false); + }); + + it('passes for a DOM element that has the expected class', function() { + var matcher = jasmineUnderTest.matchers.toHaveClass(), + el = document.createElement('div'); + + el.className = 'foo bar baz'; + + expect(matcher.compare(el, 'foo').pass).toBe(true); + expect(matcher.compare(el, 'bar').pass).toBe(true); + expect(matcher.compare(el, 'bar').pass).toBe(true); + }); + + it('fails for a DOM element that only has other classes', function() { + var matcher = jasmineUnderTest.matchers.toHaveClass(), + el = document.createElement('div'); + + el.className = 'foo bar'; + + expect(matcher.compare(el, 'fo').pass).toBe(false); + }); + + it('throws an exception when actual is not a DOM element', function() { + var matcher = jasmineUnderTest.matchers.toHaveClass(); + + expect(function() { + matcher.compare('x', 'foo'); + }).toThrowError("'x' is not a DOM element"); + + expect(function() { + matcher.compare(undefined, 'foo'); + }).toThrowError('undefined is not a DOM element'); + + expect(function() { + matcher.compare(document.createTextNode(''), 'foo') + }).toThrowError('HTMLNode is not a DOM element'); + + expect(function() { + matcher.compare({classList: ''}, 'foo'); + }).toThrowError("Object({ classList: '' }) is not a DOM element"); + }); +}); diff --git a/spec/support/jasmine.yml b/spec/support/jasmine.yml index eb6a784d..e7e989d8 100644 --- a/spec/support/jasmine.yml +++ b/spec/support/jasmine.yml @@ -12,7 +12,7 @@ src_files: - 'core/PrettyPrinter.js' - 'core/Suite.js' - 'core/**/*.js' - - 'html/**.js' + - 'html/**/*.js' - '**/*.js' stylesheets: helpers: diff --git a/src/html/matchers/toHaveClass.js b/src/html/matchers/toHaveClass.js new file mode 100644 index 00000000..e90aa106 --- /dev/null +++ b/src/html/matchers/toHaveClass.js @@ -0,0 +1,33 @@ +jasmineRequire.toHaveClass = function(j$) { + /** + * {@link expect} the actual value to be a DOM element that has the expected class + * @function + * @name matchers#toHaveClass + * @param {Object} expected - The class name to test for + * @example + * var el = document.createElement('div'); + * el.className = 'foo bar baz'; + * expect(el).toHaveClass('bar'); + */ + function toHaveClass(util, customEqualityTesters) { + return { + compare: function(actual, expected) { + if (!isElement(actual)) { + throw new Error(j$.pp(actual) + ' is not a DOM element'); + } + + return { + pass: actual.classList.contains(expected) + }; + } + }; + } + + function isElement(maybeEl) { + return maybeEl && + maybeEl.classList && + j$.isFunction_(maybeEl.classList.contains); + } + + return toHaveClass; +}; diff --git a/src/html/requireHtml.js b/src/html/requireHtml.js index b60c3ba5..8d8b7b40 100644 --- a/src/html/requireHtml.js +++ b/src/html/requireHtml.js @@ -3,4 +3,5 @@ jasmineRequire.html = function(j$) { j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); j$.QueryString = jasmineRequire.QueryString(); j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); + j$.matchers.toHaveClass = jasmineRequire.toHaveClass(j$); };